X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=radiant%2Ftextures.cpp;h=afa8d4e05c1d180b5c3f9b2e48d0e365edc60c67;hb=62a7627ffa241188e92e8417340fdf8ed5f6be82;hp=a0e0b12ba85eb713045689a4500baabdd15d9d91;hpb=9dfae1c9b270ee369c6362903a9205b30751b95f;p=xonotic%2Fnetradiant.git diff --git a/radiant/textures.cpp b/radiant/textures.cpp index a0e0b12b..afa8d4e0 100644 --- a/radiant/textures.cpp +++ b/radiant/textures.cpp @@ -40,221 +40,228 @@ #include "preferences.h" -enum ETexturesMode { - eTextures_NEAREST = 0, - eTextures_NEAREST_MIPMAP_NEAREST = 1, - eTextures_NEAREST_MIPMAP_LINEAR = 2, - eTextures_LINEAR = 3, - eTextures_LINEAR_MIPMAP_NEAREST = 4, - eTextures_LINEAR_MIPMAP_LINEAR = 5, - eTextures_MAX_ANISOTROPY = 6, -}; -enum TextureCompressionFormat { - TEXTURECOMPRESSION_NONE = 0, - TEXTURECOMPRESSION_RGBA = 1, - TEXTURECOMPRESSION_RGBA_S3TC_DXT1 = 2, - TEXTURECOMPRESSION_RGBA_S3TC_DXT3 = 3, - TEXTURECOMPRESSION_RGBA_S3TC_DXT5 = 4, +enum ETexturesMode +{ + eTextures_NEAREST = 0, + eTextures_NEAREST_MIPMAP_NEAREST = 1, + eTextures_NEAREST_MIPMAP_LINEAR = 2, + eTextures_LINEAR = 3, + eTextures_LINEAR_MIPMAP_NEAREST = 4, + eTextures_LINEAR_MIPMAP_LINEAR = 5, + eTextures_MAX_ANISOTROPY = 6, }; -struct texture_globals_t { - // RIANT - // texture compression format - TextureCompressionFormat m_nTextureCompressionFormat; - - float fGamma; - - bool bTextureCompressionSupported; // is texture compression supported by hardware? - GLint texture_components; - - // temporary values that should be initialised only once at run-time - bool m_bOpenGLCompressionSupported; - bool m_bS3CompressionSupported; - - texture_globals_t(GLint components) : - m_nTextureCompressionFormat(TEXTURECOMPRESSION_NONE), - fGamma(1.0f), - bTextureCompressionSupported(false), - texture_components(components), - m_bOpenGLCompressionSupported(false), - m_bS3CompressionSupported(false) - { - } +enum TextureCompressionFormat +{ + TEXTURECOMPRESSION_NONE = 0, + TEXTURECOMPRESSION_RGBA = 1, + TEXTURECOMPRESSION_RGBA_S3TC_DXT1 = 2, + TEXTURECOMPRESSION_RGBA_S3TC_DXT3 = 3, + TEXTURECOMPRESSION_RGBA_S3TC_DXT5 = 4, }; -texture_globals_t g_texture_globals(GL_RGBA); - -void SetTexParameters(ETexturesMode mode) +struct texture_globals_t { - float maxAniso = QGL_maxTextureAnisotropy(); - if (maxAniso > 1) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f); - } else if (mode == eTextures_MAX_ANISOTROPY) { - mode = eTextures_LINEAR_MIPMAP_LINEAR; - } + // RIANT + // texture compression format + TextureCompressionFormat m_nTextureCompressionFormat; + + float fGamma; + + bool bTextureCompressionSupported; // is texture compression supported by hardware? + GLint texture_components; + + // temporary values that should be initialised only once at run-time + bool m_bOpenGLCompressionSupported; + bool m_bS3CompressionSupported; + + texture_globals_t( GLint components ) : + m_nTextureCompressionFormat( TEXTURECOMPRESSION_NONE ), + fGamma( 1.0f ), + bTextureCompressionSupported( false ), + texture_components( components ), + m_bOpenGLCompressionSupported( false ), + m_bS3CompressionSupported( false ){ + } +}; - switch (mode) { - case eTextures_NEAREST: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case eTextures_NEAREST_MIPMAP_NEAREST: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case eTextures_NEAREST_MIPMAP_LINEAR: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case eTextures_LINEAR: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - case eTextures_LINEAR_MIPMAP_NEAREST: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - case eTextures_LINEAR_MIPMAP_LINEAR: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - case eTextures_MAX_ANISOTROPY: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso); - break; - default: - globalOutputStream() << "invalid texture mode\n"; - } +texture_globals_t g_texture_globals( GL_RGBA ); + +void SetTexParameters( ETexturesMode mode ){ + float maxAniso = QGL_maxTextureAnisotropy(); + if ( maxAniso > 1 ) { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f ); + } + else + if ( mode == eTextures_MAX_ANISOTROPY ) { + mode = eTextures_LINEAR_MIPMAP_LINEAR; + } + + switch ( mode ) + { + case eTextures_NEAREST: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + break; + case eTextures_NEAREST_MIPMAP_NEAREST: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + break; + case eTextures_NEAREST_MIPMAP_LINEAR: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + break; + case eTextures_LINEAR: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + break; + case eTextures_LINEAR_MIPMAP_NEAREST: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + break; + case eTextures_LINEAR_MIPMAP_LINEAR: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + break; + case eTextures_MAX_ANISOTROPY: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso ); + break; + default: + globalOutputStream() << "invalid texture mode\n"; + } } ETexturesMode g_texture_mode = eTextures_LINEAR_MIPMAP_LINEAR; -byte g_gammatable[256]; -void ResampleGamma(float fGamma) -{ - int i, inf; - if (fGamma == 1.0) { - for (i = 0; i < 256; i++) { - g_gammatable[i] = i; - } - } else { - for (i = 0; i < 256; i++) { - inf = (int) (255 * pow(static_cast((i + 0.5) / 255.5 ), static_cast( fGamma )) + 0.5); - if (inf < 0) { - inf = 0; - } - if (inf > 255) { - inf = 255; - } - g_gammatable[i] = inf; - } - } + +byte g_gammatable[256]; +void ResampleGamma( float fGamma ){ + int i,inf; + if ( fGamma == 1.0 ) { + for ( i = 0; i < 256; i++ ) + g_gammatable[i] = i; + } + else + { + for ( i = 0; i < 256; i++ ) + { + inf = (int)( 255 * pow( static_cast( ( i + 0.5 ) / 255.5 ), static_cast( fGamma ) ) + 0.5 ); + if ( inf < 0 ) { + inf = 0; + } + if ( inf > 255 ) { + inf = 255; + } + g_gammatable[i] = inf; + } + } } -inline const int &min_int(const int &left, const int &right) -{ - return std::min(left, right); +inline const int& min_int( const int& left, const int& right ){ + return std::min( left, right ); } int max_tex_size = 0; const int max_texture_quality = 3; -LatchedValue g_Textures_textureQuality(3, "Texture Quality"); +LatchedValue g_Textures_textureQuality( 3, "Texture Quality" ); /// \brief This function does the actual processing of raw RGBA data into a GL texture. /// It will also resample to power-of-two dimensions, generate the mipmaps and adjust gamma. -void LoadTextureRGBA(qtexture_t *q, unsigned char *pPixels, int nWidth, int nHeight) -{ - static float fGamma = -1; - float total[3]; - byte *outpixels = 0; - int nCount = nWidth * nHeight; - - if (fGamma != g_texture_globals.fGamma) { - fGamma = g_texture_globals.fGamma; - ResampleGamma(fGamma); - } - - q->width = nWidth; - q->height = nHeight; - - total[0] = total[1] = total[2] = 0.0f; - - // resample texture gamma according to user settings - for (int i = 0; i < (nCount * 4); i += 4) { - for (int j = 0; j < 3; j++) { - total[j] += (pPixels + i)[j]; - byte b = (pPixels + i)[j]; - (pPixels + i)[j] = g_gammatable[b]; - } - } - - q->color[0] = total[0] / (nCount * 255); - q->color[1] = total[1] / (nCount * 255); - q->color[2] = total[2] / (nCount * 255); - - glGenTextures(1, &q->texture_number); - - glBindTexture(GL_TEXTURE_2D, q->texture_number); - - SetTexParameters(g_texture_mode); - - int gl_width = 1; - while (gl_width < nWidth) { - gl_width <<= 1; - } - - int gl_height = 1; - while (gl_height < nHeight) { - gl_height <<= 1; - } - - bool resampled = false; - if (!(gl_width == nWidth && gl_height == nHeight)) { - resampled = true; - outpixels = (byte *) malloc(gl_width * gl_height * 4); - R_ResampleTexture(pPixels, nWidth, nHeight, outpixels, gl_width, gl_height, 4); - } else { - outpixels = pPixels; - } - - int quality_reduction = max_texture_quality - g_Textures_textureQuality.m_value; - int target_width = min_int(gl_width >> quality_reduction, max_tex_size); - int target_height = min_int(gl_height >> quality_reduction, max_tex_size); - - while (gl_width > target_width || gl_height > target_height) { - GL_MipReduce(outpixels, outpixels, gl_width, gl_height, target_width, target_height); - - if (gl_width > target_width) { - gl_width >>= 1; - } - if (gl_height > target_height) { - gl_height >>= 1; - } - } - - int mip = 0; - glTexImage2D(GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, outpixels); - while (gl_width > 1 || gl_height > 1) { - GL_MipReduce(outpixels, outpixels, gl_width, gl_height, 1, 1); - - if (gl_width > 1) { - gl_width >>= 1; - } - if (gl_height > 1) { - gl_height >>= 1; - } - - glTexImage2D(GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, outpixels); - } - - glBindTexture(GL_TEXTURE_2D, 0); - if (resampled) { - free(outpixels); - } +void LoadTextureRGBA( qtexture_t* q, unsigned char* pPixels, int nWidth, int nHeight ){ + static float fGamma = -1; + float total[3]; + byte *outpixels = 0; + int nCount = nWidth * nHeight; + + if ( fGamma != g_texture_globals.fGamma ) { + fGamma = g_texture_globals.fGamma; + ResampleGamma( fGamma ); + } + + q->width = nWidth; + q->height = nHeight; + + total[0] = total[1] = total[2] = 0.0f; + + // resample texture gamma according to user settings + for ( int i = 0; i < ( nCount * 4 ); i += 4 ) + { + for ( int j = 0; j < 3; j++ ) + { + total[j] += ( pPixels + i )[j]; + byte b = ( pPixels + i )[j]; + ( pPixels + i )[j] = g_gammatable[b]; + } + } + + q->color[0] = total[0] / ( nCount * 255 ); + q->color[1] = total[1] / ( nCount * 255 ); + q->color[2] = total[2] / ( nCount * 255 ); + + glGenTextures( 1, &q->texture_number ); + + glBindTexture( GL_TEXTURE_2D, q->texture_number ); + + SetTexParameters( g_texture_mode ); + + int gl_width = 1; + while ( gl_width < nWidth ) + gl_width <<= 1; + + int gl_height = 1; + while ( gl_height < nHeight ) + gl_height <<= 1; + + bool resampled = false; + if ( !( gl_width == nWidth && gl_height == nHeight ) ) { + resampled = true; + outpixels = (byte *)malloc( gl_width * gl_height * 4 ); + R_ResampleTexture( pPixels, nWidth, nHeight, outpixels, gl_width, gl_height, 4 ); + } + else + { + outpixels = pPixels; + } + + int quality_reduction = max_texture_quality - g_Textures_textureQuality.m_value; + int target_width = min_int( gl_width >> quality_reduction, max_tex_size ); + int target_height = min_int( gl_height >> quality_reduction, max_tex_size ); + + while ( gl_width > target_width || gl_height > target_height ) + { + GL_MipReduce( outpixels, outpixels, gl_width, gl_height, target_width, target_height ); + + if ( gl_width > target_width ) { + gl_width >>= 1; + } + if ( gl_height > target_height ) { + gl_height >>= 1; + } + } + + int mip = 0; + glTexImage2D( GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, outpixels ); + while ( gl_width > 1 || gl_height > 1 ) + { + GL_MipReduce( outpixels, outpixels, gl_width, gl_height, 1, 1 ); + + if ( gl_width > 1 ) { + gl_width >>= 1; + } + if ( gl_height > 1 ) { + gl_height >>= 1; + } + + glTexImage2D( GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, outpixels ); + } + + glBindTexture( GL_TEXTURE_2D, 0 ); + if ( resampled ) { + free( outpixels ); + } } #if 0 @@ -264,48 +271,48 @@ void LoadTextureRGBA(qtexture_t *q, unsigned char *pPixels, int nWidth, int nHei ============== */ void Texture_InitPalette( byte *pal ){ - int r,g,b; - int i; - int inf; - byte gammatable[256]; - float gamma; - - gamma = g_texture_globals.fGamma; - - if ( gamma == 1.0 ) { - for ( i = 0 ; i < 256 ; i++ ) - gammatable[i] = i; - } - else - { - for ( i = 0 ; i < 256 ; i++ ) - { - inf = (int)( 255 * pow( ( i + 0.5 ) / 255.5, gamma ) + 0.5 ); - if ( inf < 0 ) { - inf = 0; - } - if ( inf > 255 ) { - inf = 255; - } - gammatable[i] = inf; - } - } - - for ( i = 0 ; i < 256 ; i++ ) - { - r = gammatable[pal[0]]; - g = gammatable[pal[1]]; - b = gammatable[pal[2]]; - pal += 3; - - //v = (r<<24) + (g<<16) + (b<<8) + 255; - //v = BigLong (v); - - //tex_palette[i] = v; - tex_palette[i * 3 + 0] = r; - tex_palette[i * 3 + 1] = g; - tex_palette[i * 3 + 2] = b; - } + int r,g,b; + int i; + int inf; + byte gammatable[256]; + float gamma; + + gamma = g_texture_globals.fGamma; + + if ( gamma == 1.0 ) { + for ( i = 0 ; i < 256 ; i++ ) + gammatable[i] = i; + } + else + { + for ( i = 0 ; i < 256 ; i++ ) + { + inf = (int)( 255 * pow( ( i + 0.5 ) / 255.5, gamma ) + 0.5 ); + if ( inf < 0 ) { + inf = 0; + } + if ( inf > 255 ) { + inf = 255; + } + gammatable[i] = inf; + } + } + + for ( i = 0 ; i < 256 ; i++ ) + { + r = gammatable[pal[0]]; + g = gammatable[pal[1]]; + b = gammatable[pal[2]]; + pal += 3; + + //v = (r<<24) + (g<<16) + (b<<8) + 255; + //v = BigLong (v); + + //tex_palette[i] = v; + tex_palette[i * 3 + 0] = r; + tex_palette[i * 3 + 1] = g; + tex_palette[i * 3 + 2] = b; + } } #endif @@ -314,9 +321,9 @@ class TestHashtable { public: TestHashtable(){ - HashTable strings; - strings["Monkey"] = "bleh"; - strings["MonkeY"] = "blah"; + HashTable strings; + strings["Monkey"] = "bleh"; + strings["MonkeY"] = "blah"; } }; @@ -326,329 +333,300 @@ const TestHashtable g_testhashtable; typedef std::pair TextureKey; -void qtexture_realise(qtexture_t &texture, const TextureKey &key) -{ - texture.texture_number = 0; - if (!string_empty(key.second.c_str())) { - Image *image = key.first.loadImage(key.second.c_str()); - if (image != 0) { - LoadTextureRGBA(&texture, image->getRGBAPixels(), image->getWidth(), image->getHeight()); - texture.surfaceFlags = image->getSurfaceFlags(); - texture.contentFlags = image->getContentFlags(); - texture.value = image->getValue(); - image->release(); - globalOutputStream() << "Loaded Texture: \"" << key.second.c_str() << "\"\n"; - GlobalOpenGL_debugAssertNoErrors(); - } else { - globalErrorStream() << "Texture load failed: \"" << key.second.c_str() << "\"\n"; - } - } +void qtexture_realise( qtexture_t& texture, const TextureKey& key ){ + texture.texture_number = 0; + if ( !string_empty( key.second.c_str() ) ) { + Image* image = key.first.loadImage( key.second.c_str() ); + if ( image != 0 ) { + LoadTextureRGBA( &texture, image->getRGBAPixels(), image->getWidth(), image->getHeight() ); + texture.surfaceFlags = image->getSurfaceFlags(); + texture.contentFlags = image->getContentFlags(); + texture.value = image->getValue(); + image->release(); + globalOutputStream() << "Loaded Texture: \"" << key.second.c_str() << "\"\n"; + GlobalOpenGL_debugAssertNoErrors(); + } + else + { + globalErrorStream() << "Texture load failed: \"" << key.second.c_str() << "\"\n"; + } + } } -void qtexture_unrealise(qtexture_t &texture) -{ - if (GlobalOpenGL().contextValid && texture.texture_number != 0) { - glDeleteTextures(1, &texture.texture_number); - GlobalOpenGL_debugAssertNoErrors(); - } +void qtexture_unrealise( qtexture_t& texture ){ + if ( GlobalOpenGL().contextValid && texture.texture_number != 0 ) { + glDeleteTextures( 1, &texture.texture_number ); + GlobalOpenGL_debugAssertNoErrors(); + } } -class TextureKeyEqualNoCase { +class TextureKeyEqualNoCase +{ public: - bool operator()(const TextureKey &key, const TextureKey &other) const - { - return key.first == other.first && string_equal_nocase(key.second.c_str(), other.second.c_str()); - } +bool operator()( const TextureKey& key, const TextureKey& other ) const { + return key.first == other.first && string_equal_nocase( key.second.c_str(), other.second.c_str() ); +} }; -class TextureKeyHashNoCase { +class TextureKeyHashNoCase +{ public: - typedef hash_t hash_type; - - hash_t operator()(const TextureKey &key) const - { - return hash_combine(string_hash_nocase(key.second.c_str()), pod_hash(key.first)); - } +typedef hash_t hash_type; +hash_t operator()( const TextureKey& key ) const { + return hash_combine( string_hash_nocase( key.second.c_str() ), pod_hash( key.first ) ); +} }; #define DEBUG_TEXTURES 0 -class TexturesMap : public TexturesCache { - class TextureConstructor { - TexturesMap *m_cache; - public: - explicit TextureConstructor(TexturesMap *cache) - : m_cache(cache) - { - } - - qtexture_t *construct(const TextureKey &key) - { - qtexture_t *texture = new qtexture_t(key.first, key.second.c_str()); - if (m_cache->realised()) { - qtexture_realise(*texture, key); - } - return texture; - } - - void destroy(qtexture_t *texture) - { - if (m_cache->realised()) { - qtexture_unrealise(*texture); - } - delete texture; - } - }; - - typedef HashedCache qtextures_t; - qtextures_t m_qtextures; - TexturesCacheObserver *m_observer; - std::size_t m_unrealised; - +class TexturesMap : public TexturesCache +{ +class TextureConstructor +{ +TexturesMap* m_cache; public: - virtual ~TexturesMap() = default; - - TexturesMap() : m_qtextures(TextureConstructor(this)), m_observer(0), m_unrealised(1) - { - } - - typedef qtextures_t::iterator iterator; - - iterator begin() - { - return m_qtextures.begin(); - } +explicit TextureConstructor( TexturesMap* cache ) + : m_cache( cache ){ +} +qtexture_t* construct( const TextureKey& key ){ + qtexture_t* texture = new qtexture_t( key.first, key.second.c_str() ); + if ( m_cache->realised() ) { + qtexture_realise( *texture, key ); + } + return texture; +} +void destroy( qtexture_t* texture ){ + if ( m_cache->realised() ) { + qtexture_unrealise( *texture ); + } + delete texture; +} +}; - iterator end() - { - return m_qtextures.end(); - } +typedef HashedCache qtextures_t; +qtextures_t m_qtextures; +TexturesCacheObserver* m_observer; +std::size_t m_unrealised; - LoadImageCallback defaultLoader() const - { - return LoadImageCallback(0, QERApp_LoadImage); - } - - Image *loadImage(const char *name) - { - return defaultLoader().loadImage(name); - } +public: +virtual ~TexturesMap() = default; +TexturesMap() : m_qtextures( TextureConstructor( this ) ), m_observer( 0 ), m_unrealised( 1 ){ +} +typedef qtextures_t::iterator iterator; - qtexture_t *capture(const char *name) - { - return capture(defaultLoader(), name); - } +iterator begin(){ + return m_qtextures.begin(); +} +iterator end(){ + return m_qtextures.end(); +} - qtexture_t *capture(const LoadImageCallback &loader, const char *name) - { +LoadImageCallback defaultLoader() const { + return LoadImageCallback( 0, QERApp_LoadImage ); +} +Image* loadImage( const char* name ){ + return defaultLoader().loadImage( name ); +} +qtexture_t* capture( const char* name ){ + return capture( defaultLoader(), name ); +} +qtexture_t* capture( const LoadImageCallback& loader, const char* name ){ #if DEBUG_TEXTURES - globalOutputStream() << "textures capture: " << makeQuoted( name ) << '\n'; + globalOutputStream() << "textures capture: " << makeQuoted( name ) << '\n'; #endif - return m_qtextures.capture(TextureKey(loader, name)).get(); - } - - void release(qtexture_t *texture) - { + return m_qtextures.capture( TextureKey( loader, name ) ).get(); +} +void release( qtexture_t* texture ){ #if DEBUG_TEXTURES - globalOutputStream() << "textures release: " << makeQuoted( texture->name ) << '\n'; + globalOutputStream() << "textures release: " << makeQuoted( texture->name ) << '\n'; #endif - m_qtextures.release(TextureKey(texture->load, texture->name)); - } - - void attach(TexturesCacheObserver &observer) - { - ASSERT_MESSAGE(m_observer == 0, "TexturesMap::attach: cannot attach observer"); - m_observer = &observer; - } - - void detach(TexturesCacheObserver &observer) - { - ASSERT_MESSAGE(m_observer == &observer, "TexturesMap::detach: cannot detach observer"); - m_observer = 0; - } - - void realise() - { - if (--m_unrealised == 0) { - g_texture_globals.bTextureCompressionSupported = false; - - if (GlobalOpenGL().ARB_texture_compression()) { - g_texture_globals.bTextureCompressionSupported = true; - g_texture_globals.m_bOpenGLCompressionSupported = true; - } - - if (GlobalOpenGL().EXT_texture_compression_s3tc()) { - g_texture_globals.bTextureCompressionSupported = true; - g_texture_globals.m_bS3CompressionSupported = true; - } - - switch (g_texture_globals.texture_components) { - case GL_RGBA: - break; - case GL_COMPRESSED_RGBA_ARB: - if (!g_texture_globals.m_bOpenGLCompressionSupported) { - globalOutputStream() - << "OpenGL extension GL_ARB_texture_compression not supported by current graphics drivers\n"; - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; - g_texture_globals.texture_components = GL_RGBA; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - if (!g_texture_globals.m_bS3CompressionSupported) { - globalOutputStream() - << "OpenGL extension GL_EXT_texture_compression_s3tc not supported by current graphics drivers\n"; - if (g_texture_globals.m_bOpenGLCompressionSupported) { - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_RGBA; - g_texture_globals.texture_components = GL_COMPRESSED_RGBA_ARB; - } else { - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; - g_texture_globals.texture_components = GL_RGBA; - } - } - break; - default: - globalOutputStream() << "Unknown texture compression selected, reverting\n"; - g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; - g_texture_globals.texture_components = GL_RGBA; - break; - } - - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); - if (max_tex_size == 0) { - max_tex_size = 1024; - } - - for (qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i) { - if (!(*i).value.empty()) { - qtexture_realise(*(*i).value, (*i).key); - } - } - if (m_observer != 0) { - m_observer->realise(); - } - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - if (m_observer != 0) { - m_observer->unrealise(); - } - for (qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i) { - if (!(*i).value.empty()) { - qtexture_unrealise(*(*i).value); - } - } - } - } - - bool realised() - { - return m_unrealised == 0; - } + m_qtextures.release( TextureKey( texture->load, texture->name ) ); +} +void attach( TexturesCacheObserver& observer ){ + ASSERT_MESSAGE( m_observer == 0, "TexturesMap::attach: cannot attach observer" ); + m_observer = &observer; +} +void detach( TexturesCacheObserver& observer ){ + ASSERT_MESSAGE( m_observer == &observer, "TexturesMap::detach: cannot detach observer" ); + m_observer = 0; +} +void realise(){ + if ( --m_unrealised == 0 ) { + g_texture_globals.bTextureCompressionSupported = false; + + if ( GlobalOpenGL().ARB_texture_compression() ) { + g_texture_globals.bTextureCompressionSupported = true; + g_texture_globals.m_bOpenGLCompressionSupported = true; + } + + if ( GlobalOpenGL().EXT_texture_compression_s3tc() ) { + g_texture_globals.bTextureCompressionSupported = true; + g_texture_globals.m_bS3CompressionSupported = true; + } + + switch ( g_texture_globals.texture_components ) + { + case GL_RGBA: + break; + case GL_COMPRESSED_RGBA_ARB: + if ( !g_texture_globals.m_bOpenGLCompressionSupported ) { + globalOutputStream() << "OpenGL extension GL_ARB_texture_compression not supported by current graphics drivers\n"; + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; + g_texture_globals.texture_components = GL_RGBA; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + if ( !g_texture_globals.m_bS3CompressionSupported ) { + globalOutputStream() << "OpenGL extension GL_EXT_texture_compression_s3tc not supported by current graphics drivers\n"; + if ( g_texture_globals.m_bOpenGLCompressionSupported ) { + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_RGBA; + g_texture_globals.texture_components = GL_COMPRESSED_RGBA_ARB; + } + else + { + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; + g_texture_globals.texture_components = GL_RGBA; + } + } + break; + default: + globalOutputStream() << "Unknown texture compression selected, reverting\n"; + g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE; + g_texture_globals.texture_components = GL_RGBA; + break; + } + + + glGetIntegerv( GL_MAX_TEXTURE_SIZE, &max_tex_size ); + if ( max_tex_size == 0 ) { + max_tex_size = 1024; + } + + for ( qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i ) + { + if ( !( *i ).value.empty() ) { + qtexture_realise( *( *i ).value, ( *i ).key ); + } + } + if ( m_observer != 0 ) { + m_observer->realise(); + } + } +} +void unrealise(){ + if ( ++m_unrealised == 1 ) { + if ( m_observer != 0 ) { + m_observer->unrealise(); + } + for ( qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i ) + { + if ( !( *i ).value.empty() ) { + qtexture_unrealise( *( *i ).value ); + } + } + } +} +bool realised(){ + return m_unrealised == 0; +} }; -TexturesMap *g_texturesmap; +TexturesMap* g_texturesmap; -TexturesCache &GetTexturesCache() -{ - return *g_texturesmap; +TexturesCache& GetTexturesCache(){ + return *g_texturesmap; } -void Textures_Realise() -{ - g_texturesmap->realise(); +void Textures_Realise(){ + g_texturesmap->realise(); } -void Textures_Unrealise() -{ - g_texturesmap->unrealise(); +void Textures_Unrealise(){ + g_texturesmap->unrealise(); } Callback g_texturesModeChangedNotify; -void Textures_setModeChangedNotify(const Callback ¬ify) -{ - g_texturesModeChangedNotify = notify; +void Textures_setModeChangedNotify( const Callback& notify ){ + g_texturesModeChangedNotify = notify; } -void Textures_ModeChanged() -{ - if (g_texturesmap->realised()) { - SetTexParameters(g_texture_mode); +void Textures_ModeChanged(){ + if ( g_texturesmap->realised() ) { + SetTexParameters( g_texture_mode ); - for (TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i) { - glBindTexture(GL_TEXTURE_2D, (*i).value->texture_number); - SetTexParameters(g_texture_mode); - } + for ( TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i ) + { + glBindTexture( GL_TEXTURE_2D, ( *i ).value->texture_number ); + SetTexParameters( g_texture_mode ); + } - glBindTexture(GL_TEXTURE_2D, 0); - } - g_texturesModeChangedNotify(); + glBindTexture( GL_TEXTURE_2D, 0 ); + } + g_texturesModeChangedNotify(); } -void Textures_SetMode(ETexturesMode mode) -{ - if (g_texture_mode != mode) { - g_texture_mode = mode; +void Textures_SetMode( ETexturesMode mode ){ + if ( g_texture_mode != mode ) { + g_texture_mode = mode; - Textures_ModeChanged(); - } + Textures_ModeChanged(); + } } -void Textures_setTextureComponents(GLint texture_components) -{ - if (g_texture_globals.texture_components != texture_components) { - Textures_Unrealise(); - g_texture_globals.texture_components = texture_components; - Textures_Realise(); - } +void Textures_setTextureComponents( GLint texture_components ){ + if ( g_texture_globals.texture_components != texture_components ) { + Textures_Unrealise(); + g_texture_globals.texture_components = texture_components; + Textures_Realise(); + } } -void Textures_UpdateTextureCompressionFormat() -{ - GLint texture_components = GL_RGBA; - - switch (g_texture_globals.m_nTextureCompressionFormat) { - case (TEXTURECOMPRESSION_NONE): { - texture_components = GL_RGBA; - break; - } - case (TEXTURECOMPRESSION_RGBA): { - texture_components = GL_COMPRESSED_RGBA_ARB; - break; - } - case (TEXTURECOMPRESSION_RGBA_S3TC_DXT1): { - texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - break; - } - case (TEXTURECOMPRESSION_RGBA_S3TC_DXT3): { - texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - break; - } - case (TEXTURECOMPRESSION_RGBA_S3TC_DXT5): { - texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - break; - } - } - - Textures_setTextureComponents(texture_components); +void Textures_UpdateTextureCompressionFormat(){ + GLint texture_components = GL_RGBA; + + switch ( g_texture_globals.m_nTextureCompressionFormat ) + { + case ( TEXTURECOMPRESSION_NONE ): + { + texture_components = GL_RGBA; + break; + } + case ( TEXTURECOMPRESSION_RGBA ): + { + texture_components = GL_COMPRESSED_RGBA_ARB; + break; + } + case ( TEXTURECOMPRESSION_RGBA_S3TC_DXT1 ): + { + texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + break; + } + case ( TEXTURECOMPRESSION_RGBA_S3TC_DXT3 ): + { + texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + } + case ( TEXTURECOMPRESSION_RGBA_S3TC_DXT5 ): + { + texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + } + } + + Textures_setTextureComponents( texture_components ); } struct TextureCompression { - static void Export(const TextureCompressionFormat &self, const Callback &returnz) - { + static void Export(const TextureCompressionFormat &self, const Callback &returnz) { returnz(self); } - static void Import(TextureCompressionFormat &self, int value) - { + static void Import(TextureCompressionFormat &self, int value) { if (!g_texture_globals.m_bOpenGLCompressionSupported && g_texture_globals.m_bS3CompressionSupported && value >= 1) { @@ -676,24 +654,21 @@ struct TextureCompression { }; struct TextureGamma { - static void Export(const float &self, const Callback &returnz) - { - returnz(self); - } - - static void Import(float &self, float value) - { - if (value != self) { - Textures_Unrealise(); - self = value; - Textures_Realise(); - } - } + static void Export(const float &self, const Callback &returnz) { + returnz(self); + } + + static void Import(float &self, float value) { + if (value != self) { + Textures_Unrealise(); + self = value; + Textures_Realise(); + } + } }; struct TextureMode { - static void Export(const ETexturesMode &self, const Callback &returnz) - { + static void Export(const ETexturesMode &self, const Callback &returnz) { switch (self) { case eTextures_NEAREST: returnz(0); @@ -721,8 +696,7 @@ struct TextureMode { } } - static void Import(ETexturesMode &self, int value) - { + static void Import(ETexturesMode &self, int value) { switch (value) { case 0: Textures_SetMode(eTextures_NEAREST); @@ -748,100 +722,86 @@ struct TextureMode { } }; -void Textures_constructPreferences(PreferencesPage &page) -{ - { - const char *percentages[] = {"12.5%", "25%", "50%", "100%",}; - page.appendRadio( - "Texture Quality", - STRING_ARRAY_RANGE(percentages), - make_property(g_Textures_textureQuality) - ); - } - page.appendSpinner( - "Texture Gamma", - 1.0, - 0.0, - 1.0, - make_property(g_texture_globals.fGamma) - ); - { - const char *texture_mode[] = {"Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear", - "Anisotropy"}; - page.appendCombo( - "Texture Render Mode", - STRING_ARRAY_RANGE(texture_mode), - make_property(g_texture_mode) - ); - } - { - const char *compression_none[] = {"None"}; - const char *compression_opengl[] = {"None", "OpenGL ARB"}; - const char *compression_s3tc[] = {"None", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5"}; - const char *compression_opengl_s3tc[] = {"None", "OpenGL ARB", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5"}; - StringArrayRange compression( - (g_texture_globals.m_bOpenGLCompressionSupported) - ? (g_texture_globals.m_bS3CompressionSupported) - ? STRING_ARRAY_RANGE(compression_opengl_s3tc) - : STRING_ARRAY_RANGE(compression_opengl) - : (g_texture_globals.m_bS3CompressionSupported) - ? STRING_ARRAY_RANGE(compression_s3tc) - : STRING_ARRAY_RANGE(compression_none) - ); - page.appendCombo( - "Hardware Texture Compression", - compression, - make_property(g_texture_globals.m_nTextureCompressionFormat) - ); - } +void Textures_constructPreferences( PreferencesPage& page ){ + { + const char* percentages[] = { "12.5%", "25%", "50%", "100%", }; + page.appendRadio( + "Texture Quality", + STRING_ARRAY_RANGE( percentages ), + make_property( g_Textures_textureQuality ) + ); + } + page.appendSpinner( + "Texture Gamma", + 1.0, + 0.0, + 1.0, + make_property(g_texture_globals.fGamma) + ); + { + const char* texture_mode[] = { "Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear", "Anisotropy" }; + page.appendCombo( + "Texture Render Mode", + STRING_ARRAY_RANGE( texture_mode ), + make_property(g_texture_mode) + ); + } + { + const char* compression_none[] = { "None" }; + const char* compression_opengl[] = { "None", "OpenGL ARB" }; + const char* compression_s3tc[] = { "None", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5" }; + const char* compression_opengl_s3tc[] = { "None", "OpenGL ARB", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5" }; + StringArrayRange compression( + ( g_texture_globals.m_bOpenGLCompressionSupported ) + ? ( g_texture_globals.m_bS3CompressionSupported ) + ? STRING_ARRAY_RANGE( compression_opengl_s3tc ) + : STRING_ARRAY_RANGE( compression_opengl ) + : ( g_texture_globals.m_bS3CompressionSupported ) + ? STRING_ARRAY_RANGE( compression_s3tc ) + : STRING_ARRAY_RANGE( compression_none ) + ); + page.appendCombo( + "Hardware Texture Compression", + compression, + make_property(g_texture_globals.m_nTextureCompressionFormat) + ); + } } - -void Textures_constructPage(PreferenceGroup &group) -{ - PreferencesPage page(group.createPage("Textures", "Texture Settings")); - Textures_constructPreferences(page); +void Textures_constructPage( PreferenceGroup& group ){ + PreferencesPage page( group.createPage( "Textures", "Texture Settings" ) ); + Textures_constructPreferences( page ); } - -void Textures_registerPreferencesPage() -{ - PreferencesDialog_addDisplayPage(makeCallbackF(Textures_constructPage)); +void Textures_registerPreferencesPage(){ + PreferencesDialog_addDisplayPage( makeCallbackF(Textures_constructPage) ); } struct TextureCompressionPreference { - static void Export(const Callback &returnz) - { - returnz(g_texture_globals.m_nTextureCompressionFormat); - } - - static void Import(int value) - { - g_texture_globals.m_nTextureCompressionFormat = static_cast( value ); - Textures_UpdateTextureCompressionFormat(); - } + static void Export(const Callback &returnz) { + returnz(g_texture_globals.m_nTextureCompressionFormat); + } + + static void Import(int value) { + g_texture_globals.m_nTextureCompressionFormat = static_cast( value ); + Textures_UpdateTextureCompressionFormat(); + } }; -void Textures_Construct() -{ - g_texturesmap = new TexturesMap; +void Textures_Construct(){ + g_texturesmap = new TexturesMap; - GlobalPreferenceSystem().registerPreference("TextureCompressionFormat", - make_property_string()); - GlobalPreferenceSystem().registerPreference("TextureFiltering", - make_property_string(reinterpret_cast( g_texture_mode ))); - GlobalPreferenceSystem().registerPreference("TextureQuality", - make_property_string(g_Textures_textureQuality.m_latched)); - GlobalPreferenceSystem().registerPreference("SI_Gamma", make_property_string(g_texture_globals.fGamma)); + GlobalPreferenceSystem().registerPreference( "TextureCompressionFormat", make_property_string() ); + GlobalPreferenceSystem().registerPreference( "TextureFiltering", make_property_string( reinterpret_cast( g_texture_mode ) ) ); + GlobalPreferenceSystem().registerPreference( "TextureQuality", make_property_string( g_Textures_textureQuality.m_latched ) ); + GlobalPreferenceSystem().registerPreference( "SI_Gamma", make_property_string( g_texture_globals.fGamma ) ); - g_Textures_textureQuality.useLatched(); + g_Textures_textureQuality.useLatched(); - Textures_registerPreferencesPage(); + Textures_registerPreferencesPage(); - Textures_ModeChanged(); + Textures_ModeChanged(); } - -void Textures_Destroy() -{ - delete g_texturesmap; +void Textures_Destroy(){ + delete g_texturesmap; } @@ -850,52 +810,52 @@ void Textures_Destroy() #include "modulesystem/moduleregistry.h" class TexturesDependencies : - public GlobalRadiantModuleRef, - public GlobalOpenGLModuleRef, - public GlobalPreferenceSystemModuleRef { - ImageModulesRef m_image_modules; + public GlobalRadiantModuleRef, + public GlobalOpenGLModuleRef, + public GlobalPreferenceSystemModuleRef +{ +ImageModulesRef m_image_modules; +ImageModulesRef m_fallback_image_modules; public: - TexturesDependencies() : - m_image_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("texturetypes")) - { - } - - ImageModules &getImageModules() - { - return m_image_modules.get(); - } +TexturesDependencies() : + m_image_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "texturetypes" ) ), + m_fallback_image_modules( "png" ){ +} +ImageModules& getImageModules(){ + return m_image_modules.get(); +} +ImageModules& getFallbackImageModules(){ + return m_fallback_image_modules.get(); +} }; -class TexturesAPI { - TexturesCache *m_textures; +class TexturesAPI +{ +TexturesCache* m_textures; public: - typedef TexturesCache Type; +typedef TexturesCache Type; +STRING_CONSTANT( Name, "*" ); - STRING_CONSTANT(Name, "*"); +TexturesAPI(){ + Textures_Construct(); - TexturesAPI() - { - Textures_Construct(); - - m_textures = &GetTexturesCache(); - } - - ~TexturesAPI() - { - Textures_Destroy(); - } - - TexturesCache *getTable() - { - return m_textures; - } + m_textures = &GetTexturesCache(); +} +~TexturesAPI(){ + Textures_Destroy(); +} +TexturesCache* getTable(){ + return m_textures; +} }; typedef SingletonModule TexturesModule; typedef Static StaticTexturesModule; -StaticRegisterModule staticRegisterTextures(StaticTexturesModule::instance()); +StaticRegisterModule staticRegisterTextures( StaticTexturesModule::instance() ); -ImageModules &Textures_getImageModules() -{ - return StaticTexturesModule::instance().getDependencies().getImageModules(); +ImageModules& Textures_getImageModules(){ + return StaticTexturesModule::instance().getDependencies().getImageModules(); +} +ImageModules& Textures_getFallbackImageModules(){ + return StaticTexturesModule::instance().getDependencies().getFallbackImageModules(); }