--- Irrlicht.old/COpenGLDriver.h 2005-11-27 12:11:42.000000000 +0100 +++ Irrlicht/COpenGLDriver.h 2005-12-20 22:11:06.000000000 +0100 @@ -172,6 +172,10 @@ virtual core::matrix4 getTransform(E_TRANSFORMATION_STATE state); // public access to the (loaded) extensions. + void extGlCompressedTexImage2D(GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLsizei height, GLint border, GLsizei imageSize, + const void *data); void extGlActiveTextureARB(GLenum texture); void extGlClientActiveTextureARB(GLenum texture); void extGlGenProgramsARB(GLsizei n, GLuint *programs); @@ -302,6 +306,7 @@ bool ARBFragmentProgramExtension; //GL_ARB_fragment_program bool ARBShadingLanguage100Extension; bool AnisotropyExtension; + bool TextureCompressionExtension; SMaterial Material, LastMaterial; COpenGLTexture* RenderTargetTexture; @@ -326,6 +331,7 @@ PFNGLDELETEPROGRAMSNVPROC pGlDeleteProgramsARB; PFNGLPROGRAMLOCALPARAMETER4FVARBPROC pGlProgramLocalParameter4fvARB; #endif + PFNGLCOMPRESSEDTEXIMAGE2DPROC pGlCompressedTexImage2D; PFNGLCREATESHADEROBJECTARBPROC pGlCreateShaderObjectARB; PFNGLSHADERSOURCEARBPROC pGlShaderSourceARB; PFNGLCOMPILESHADERARBPROC pGlCompileShaderARB; --- Irrlicht.old/COpenGLDriver.cpp 2005-11-30 20:02:54.000000000 +0100 +++ Irrlicht/COpenGLDriver.cpp 2005-12-20 22:11:06.000000000 +0100 @@ -42,8 +42,8 @@ pGlLinkProgramARB(0), pGlUseProgramObjectARB(0), pGlDeleteObjectARB(0), pGlGetObjectParameterivARB(0), pGlGetUniformLocationARB(0), pGlUniform4fvARB(0), pGlUniform1fvARB(0), pGlUniform2fvARB(0), pGlUniform3fvARB(0), pGlUniformMatrix2fvARB(0), - pGlUniformMatrix3fvARB(0), pGlUniformMatrix4fvARB(0), pGlGetActiveUniformARB(0) - + pGlUniformMatrix3fvARB(0), pGlUniformMatrix4fvARB(0), pGlGetActiveUniformARB(0), + TextureCompressionExtension(false), pGlCompressedTexImage2D(0) { #ifdef _DEBUG setDebugName("COpenGLDriver"); @@ -345,6 +345,9 @@ else if (strstr(p, "GL_EXT_texture_filter_anisotropic")) AnisotropyExtension = true; + else + if (strstr(p, "GL_ARB_texture_compression")) + TextureCompressionExtension = true; p = p + strlen(p) + 1; } @@ -367,6 +370,8 @@ os::Printer::log("Failed to load OpenGL's multitexture extension, proceeding without.", ELL_WARNING); } + pGlCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) wglGetProcAddress("glCompressedTexImage2D"); + // get fragment and vertex program function pointers pGlGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) wglGetProcAddress("glGenProgramsARB"); pGlBindProgramARB = (PFNGLBINDPROGRAMARBPROC) wglGetProcAddress("glBindProgramARB"); @@ -1322,7 +1327,7 @@ { bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); - return new COpenGLTexture(surface, generateMipLevels); + return new COpenGLTexture(surface, generateMipLevels, this); } @@ -1960,6 +1965,15 @@ return EDT_OPENGL; } +void COpenGLDriver::extGlCompressedTexImage2D(GLenum trgt, GLint level, GLenum intformat, GLsizei width, + GLsizei height, GLint border, GLsizei imageSize, const void *data) +{ +#if defined(_IRR_WINDOWS_) || defined(_IRR_LINUX_OPENGL_USE_EXTENSIONS_) + if (pGlCompressedTexImage2D) + pGlCompressedTexImage2D(trgt, level, intformat, width, height, border, imageSize, data); +#endif +} + void COpenGLDriver::extGlActiveTextureARB(GLenum texture) { #if defined(_IRR_WINDOWS_) || defined(_IRR_LINUX_OPENGL_USE_EXTENSIONS_) --- Irrlicht.old/COpenGLTexture.h 2005-08-20 21:17:48.000000000 +0200 +++ Irrlicht/COpenGLTexture.h 2005-12-21 08:35:08.000000000 +0100 @@ -7,6 +7,7 @@ #include "ITexture.h" #include "IImage.h" +#include "COpenGLDriver.h" #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ @@ -42,7 +43,7 @@ public: //! constructor - COpenGLTexture(IImage* surface, bool generateMipLevels); + COpenGLTexture(IImage* surface, bool generateMipLevels, COpenGLDriver* driver=0); //! destructor virtual ~COpenGLTexture(); @@ -65,6 +66,9 @@ //! returns color format of texture virtual ECOLOR_FORMAT getColorFormat(); + //! returns type flags of texture + virtual EIMAGE_TYPE getImageType(); + //! returns pitch of texture (in bytes) virtual s32 getPitch(); @@ -80,7 +84,7 @@ void getImageData(IImage* image); //! copies the the texture into an open gl texture. - void copyTexture(); + void copyTexture(COpenGLDriver* driver=0); //! returns the size of a texture which would be the optimize size for rendering it inline s32 getTextureSizeFromSurfaceSize(s32 size); @@ -96,6 +100,9 @@ s32* ImageData; GLuint TextureName; + ECOLOR_FORMAT Format; + EIMAGE_TYPE Type; + u32 NumMipMaps; bool hasMipMaps; }; --- Irrlicht.old/COpenGLTexture.cpp 2005-08-20 21:21:58.000000000 +0200 +++ Irrlicht/COpenGLTexture.cpp 2005-12-21 08:53:36.000000000 +0100 @@ -6,6 +6,7 @@ #include "COpenGLTexture.h" #include "os.h" #include "CColorConverter.h" +#include "COpenGLDriver.h" #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ @@ -18,9 +19,9 @@ { //! constructor -COpenGLTexture::COpenGLTexture(IImage* image, bool generateMipLevels) +COpenGLTexture::COpenGLTexture(IImage* image, bool generateMipLevels, COpenGLDriver* driver) : Pitch(0), ImageSize(0,0), hasMipMaps(generateMipLevels), -ImageData(0), TextureName(0) +ImageData(0), TextureName(0), Format(ECF_A8R8G8B8), Type(EIT_IMAGE_2D) { #ifdef _DEBUG setDebugName("COpenGLTexture"); @@ -37,7 +38,7 @@ if (ImageData) { glGenTextures(1, &TextureName); - copyTexture(); + copyTexture(driver); } } } @@ -53,6 +54,29 @@ void COpenGLTexture::getImageData(IImage* image) { + /* + Note that the following part will only be used for images with a color format that is only used for dds files. + Nothing but DDS should be affected by any of these changes. + + This part assumes that the image already has proper dimensions and especially for 3D or cubemaps the + dimensions will obviously contain nonsense. The ImageDate will also be deleted after creating the texture + as a) editing it wouldn't make too much sense and b) with OpenGLs internal copy there is no reason to have + three completely redundant and memory wasting copies flying around. If there is any need to touch the image + data, OpenGL should be asked to return a pointer to it. + */ + Type = image->getImageType(); + ECOLOR_FORMAT fmt = image->getColorFormat(); + NumMipMaps = image->getNumMipMaps(); + if (fmt==ECF_BGRA8 || fmt==ECF_DXT1 || fmt==ECF_DXT3 || fmt==ECF_DXT5) { + Format = fmt; + ImageSize = image->getDimension(); + ImageData = new s32[image->getDataSize()]; + memcpy(ImageData, (s32*)image->lock(), image->getDataSize()); + image->unlock(); + return; + } + /**/ + ImageSize = image->getDimension(); OriginalSize = ImageSize; @@ -164,44 +186,81 @@ //! copies the texture into an open gl texture. -void COpenGLTexture::copyTexture() -{ - glBindTexture(GL_TEXTURE_2D, TextureName); - if (testError()) - os::Printer::log("Could not bind Texture", ELL_ERROR); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImageSize.Width, +void COpenGLTexture::copyTexture(COpenGLDriver* driver) { + /* + The changes will not make volume or cube maps available. setTexture would need to be changed + to bind the texture based on its actual type, but both types require 3D tex coords, which Irrlicht + doesn't seem to support without more changes. + These two types are not enabled, as there is no reason to cause trouble with systems not supporting + them if they won't work anyway + */ + + //if (Type & EIT_IMAGE_2D) + glBindTexture(GL_TEXTURE_2D, TextureName); + //else if (Type & EIT_IMAGE_3D) glBindTexture(GL_TEXTURE_3D, TextureName); + //else if (Type & EIT_CUBE_MAP) glBindTexture(GL_TEXTURE_CUBE_MAP, TextureName); + if (testError()) os::Printer::log("Could not bind Texture", ELL_ERROR); + + bool compressed=false; + int fmt = GL_RGBA; + int blockSize = 16; + if (Format==ECF_DXT1) {fmt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; compressed=true; blockSize=8;} + if (Format==ECF_DXT3) {fmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; compressed=true;} + if (Format==ECF_DXT5) {fmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; compressed=true;} + /**/ + if ( +#ifdef DISABLE_MIPMAPPING + true +#else + //If we dont want mipmaps or have a dds without mipmap levels + !hasMipMaps || (compressed && NumMipMaps<=1) +#endif + ) + { + if (compressed && driver) { + int levelSize = ((ImageSize.Width+3)/4)*((ImageSize.Height+3)/4)*blockSize; + driver->extGlCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, ImageSize.Width, + ImageSize.Height, 0, levelSize, ImageData); + if (testError()) os::Printer::log("Could not glCompressedTexImage2D", ELL_ERROR); + } + else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImageSize.Width, ImageSize.Height, 0, GL_BGRA_EXT , GL_UNSIGNED_BYTE, ImageData); if (testError()) os::Printer::log("Could not glTexImage2D", ELL_ERROR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (hasMipMaps) - { - s32 ret = 0; - + } + else { #ifndef DISABLE_MIPMAPPING - ret = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, ImageSize.Width, ImageSize.Height, + s32 ret = 0; + if (compressed && driver) { + int lvlSize; + int width = ImageSize.Width, height = ImageSize.Height; + for (unsigned i=0, offset=0; iextGlCompressedTexImage2D(GL_TEXTURE_2D, i, fmt, + width, height, 0, lvlSize, (u8*)ImageData + offset); + if (testError()) os::Printer::log("Could not glCompressedTexImage2D", ELL_ERROR); + offset += lvlSize; + if (width>1) width >>= 1; + if (height>1) height >>= 1; + } + } + else + s32 ret = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, ImageSize.Width, ImageSize.Height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, ImageData); - #endif - - if (ret) - { - #ifndef DISABLE_MIPMAPPING + if (ret) { os::Printer::log("Could not create OpenGL texture mip maps.", (c8*)gluErrorString(ret), ELL_ERROR); + return; + } + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); #else os::Printer::log("Did not create OpenGL texture mip maps.", ELL_ERROR); #endif } - else - { - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - } - } } @@ -259,7 +318,11 @@ return ECF_A8R8G8B8; } - +//! returns type flags of texture +EIMAGE_TYPE COpenGLTexture::getImageType() +{ + return Type; +} //! returns pitch of texture (in bytes) s32 COpenGLTexture::getPitch()