2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "debugging/debugging.h"
27 #include "itextures.h"
29 #include "preferencesystem.h"
32 #include "texturelib.h"
33 #include "container/hashfunc.h"
34 #include "container/cache.h"
35 #include "generic/callback.h"
40 #include "preferences.h"
44 eTextures_NEAREST = 0,
45 eTextures_NEAREST_MIPMAP_NEAREST = 1,
46 eTextures_NEAREST_MIPMAP_LINEAR = 2,
48 eTextures_LINEAR_MIPMAP_NEAREST = 4,
49 eTextures_LINEAR_MIPMAP_LINEAR = 5,
50 eTextures_MAX_ANISOTROPY = 6,
53 enum TextureCompressionFormat {
54 TEXTURECOMPRESSION_NONE = 0,
55 TEXTURECOMPRESSION_RGBA = 1,
56 TEXTURECOMPRESSION_RGBA_S3TC_DXT1 = 2,
57 TEXTURECOMPRESSION_RGBA_S3TC_DXT3 = 3,
58 TEXTURECOMPRESSION_RGBA_S3TC_DXT5 = 4,
61 struct texture_globals_t {
63 // texture compression format
64 TextureCompressionFormat m_nTextureCompressionFormat;
68 bool bTextureCompressionSupported; // is texture compression supported by hardware?
69 GLint texture_components;
71 // temporary values that should be initialised only once at run-time
72 bool m_bOpenGLCompressionSupported;
73 bool m_bS3CompressionSupported;
75 texture_globals_t(GLint components) :
76 m_nTextureCompressionFormat(TEXTURECOMPRESSION_NONE),
78 bTextureCompressionSupported(false),
79 texture_components(components),
80 m_bOpenGLCompressionSupported(false),
81 m_bS3CompressionSupported(false)
86 texture_globals_t g_texture_globals(GL_RGBA);
88 void SetTexParameters(OpenGLBinding &GL, ETexturesMode mode)
90 float maxAniso = QGL_maxTextureAnisotropy();
92 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
93 } else if (mode == eTextures_MAX_ANISOTROPY) {
94 mode = eTextures_LINEAR_MIPMAP_LINEAR;
98 case eTextures_NEAREST:
99 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
100 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
102 case eTextures_NEAREST_MIPMAP_NEAREST:
103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
106 case eTextures_NEAREST_MIPMAP_LINEAR:
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
110 case eTextures_LINEAR:
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
114 case eTextures_LINEAR_MIPMAP_NEAREST:
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
118 case eTextures_LINEAR_MIPMAP_LINEAR:
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
122 case eTextures_MAX_ANISOTROPY:
123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);
126 globalOutputStream() << "invalid texture mode\n";
130 ETexturesMode g_texture_mode = eTextures_LINEAR_MIPMAP_LINEAR;
133 byte g_gammatable[256];
135 void ResampleGamma(float fGamma)
139 for (i = 0; i < 256; i++) {
143 for (i = 0; i < 256; i++) {
144 inf = (int) (255 * pow(static_cast<double>((i + 0.5) / 255.5 ), static_cast<double>( fGamma )) + 0.5);
151 g_gammatable[i] = inf;
156 inline const int &min_int(const int &left, const int &right)
158 return std::min(left, right);
161 int max_tex_size = 0;
162 const int max_texture_quality = 3;
163 LatchedValue<int> g_Textures_textureQuality(3, "Texture Quality");
165 /// \brief This function does the actual processing of raw RGBA data into a GL texture.
166 /// It will also resample to power-of-two dimensions, generate the mipmaps and adjust gamma.
167 void LoadTextureRGBA(OpenGLBinding &GL, qtexture_t *q, unsigned char *pPixels, int nWidth, int nHeight)
169 static float fGamma = -1;
172 int nCount = nWidth * nHeight;
174 if (fGamma != g_texture_globals.fGamma) {
175 fGamma = g_texture_globals.fGamma;
176 ResampleGamma(fGamma);
182 total[0] = total[1] = total[2] = 0.0f;
184 // resample texture gamma according to user settings
185 for (int i = 0; i < (nCount * 4); i += 4) {
186 for (int j = 0; j < 3; j++) {
187 total[j] += (pPixels + i)[j];
188 byte b = (pPixels + i)[j];
189 (pPixels + i)[j] = g_gammatable[b];
193 q->color[0] = total[0] / (nCount * 255);
194 q->color[1] = total[1] / (nCount * 255);
195 q->color[2] = total[2] / (nCount * 255);
197 glGenTextures(1, &q->texture_number);
199 glBindTexture(GL_TEXTURE_2D, q->texture_number);
201 SetTexParameters(GL, g_texture_mode);
204 while (gl_width < nWidth) {
209 while (gl_height < nHeight) {
213 bool resampled = false;
214 if (!(gl_width == nWidth && gl_height == nHeight)) {
216 outpixels = (byte *) malloc(gl_width * gl_height * 4);
217 R_ResampleTexture(pPixels, nWidth, nHeight, outpixels, gl_width, gl_height, 4);
222 int quality_reduction = max_texture_quality - g_Textures_textureQuality.m_value;
223 int target_width = min_int(gl_width >> quality_reduction, max_tex_size);
224 int target_height = min_int(gl_height >> quality_reduction, max_tex_size);
226 while (gl_width > target_width || gl_height > target_height) {
227 GL_MipReduce(outpixels, outpixels, gl_width, gl_height, target_width, target_height);
229 if (gl_width > target_width) {
232 if (gl_height > target_height) {
238 glTexImage2D(GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA,
239 GL_UNSIGNED_BYTE, outpixels);
240 while (gl_width > 1 || gl_height > 1) {
241 GL_MipReduce(outpixels, outpixels, gl_width, gl_height, 1, 1);
250 glTexImage2D(GL_TEXTURE_2D, mip++, g_texture_globals.texture_components, gl_width, gl_height, 0, GL_RGBA,
251 GL_UNSIGNED_BYTE, outpixels);
254 glBindTexture(GL_TEXTURE_2D, 0);
266 void Texture_InitPalette( byte *pal ){
270 byte gammatable[256];
273 gamma = g_texture_globals.fGamma;
275 if ( gamma == 1.0 ) {
276 for ( i = 0 ; i < 256 ; i++ )
281 for ( i = 0 ; i < 256 ; i++ )
283 inf = (int)( 255 * pow( ( i + 0.5 ) / 255.5, gamma ) + 0.5 );
294 for ( i = 0 ; i < 256 ; i++ )
296 r = gammatable[pal[0]];
297 g = gammatable[pal[1]];
298 b = gammatable[pal[2]];
301 //v = (r<<24) + (g<<16) + (b<<8) + 255;
304 //tex_palette[i] = v;
305 tex_palette[i * 3 + 0] = r;
306 tex_palette[i * 3 + 1] = g;
307 tex_palette[i * 3 + 2] = b;
317 HashTable<CopiedString, CopiedString, HashStringNoCase, StringEqualNoCase> strings;
318 strings["Monkey"] = "bleh";
319 strings["MonkeY"] = "blah";
323 const TestHashtable g_testhashtable;
327 typedef std::pair<LoadImageCallback, CopiedString> TextureKey;
329 void qtexture_realise(OpenGLBinding &GL, qtexture_t &texture, const TextureKey &key)
331 texture.texture_number = 0;
332 if (!string_empty(key.second.c_str())) {
333 Image *image = key.first.loadImage(key.second.c_str());
335 LoadTextureRGBA(GL, &texture, image->getRGBAPixels(), image->getWidth(), image->getHeight());
336 texture.surfaceFlags = image->getSurfaceFlags();
337 texture.contentFlags = image->getContentFlags();
338 texture.value = image->getValue();
340 globalOutputStream() << "Loaded Texture: \"" << key.second.c_str() << "\"\n";
341 GlobalOpenGL_debugAssertNoErrors();
343 globalErrorStream() << "Texture load failed: \"" << key.second.c_str() << "\"\n";
348 void qtexture_unrealise(OpenGLBinding &GL, qtexture_t &texture)
350 if (GL.contextValid && texture.texture_number != 0) {
351 glDeleteTextures(1, &texture.texture_number);
352 GlobalOpenGL_debugAssertNoErrors();
356 class TextureKeyEqualNoCase {
358 bool operator()(const TextureKey &key, const TextureKey &other) const
360 return key.first == other.first && string_equal_nocase(key.second.c_str(), other.second.c_str());
364 class TextureKeyHashNoCase {
366 typedef hash_t hash_type;
368 hash_t operator()(const TextureKey &key) const
370 return hash_combine(string_hash_nocase(key.second.c_str()), pod_hash(key.first));
374 #define DEBUG_TEXTURES 0
376 class TexturesMap : public TexturesCache {
377 class TextureConstructor {
378 TexturesMap *m_cache;
380 explicit TextureConstructor(TexturesMap *cache)
385 qtexture_t *construct(const TextureKey &key)
387 OpenGLBinding &GL = GlobalOpenGL();
388 qtexture_t *texture = new qtexture_t(key.first, key.second.c_str());
389 if (m_cache->realised()) {
390 qtexture_realise(GL, *texture, key);
395 void destroy(qtexture_t *texture)
397 OpenGLBinding &GL = GlobalOpenGL();
398 if (m_cache->realised()) {
399 qtexture_unrealise(GL, *texture);
405 typedef HashedCache<TextureKey, qtexture_t, TextureKeyHashNoCase, TextureKeyEqualNoCase, TextureConstructor> qtextures_t;
406 qtextures_t m_qtextures;
407 TexturesCacheObserver *m_observer;
408 std::size_t m_unrealised;
411 virtual ~TexturesMap() = default;
413 TexturesMap() : m_qtextures(TextureConstructor(this)), m_observer(0), m_unrealised(1)
417 typedef qtextures_t::iterator iterator;
421 return m_qtextures.begin();
426 return m_qtextures.end();
429 LoadImageCallback defaultLoader() const
431 return LoadImageCallback(0, QERApp_LoadImage);
434 Image *loadImage(const char *name)
436 return defaultLoader().loadImage(name);
439 qtexture_t *capture(const char *name)
441 return capture(defaultLoader(), name);
444 qtexture_t *capture(const LoadImageCallback &loader, const char *name)
447 globalOutputStream() << "textures capture: " << makeQuoted( name ) << '\n';
449 return m_qtextures.capture(TextureKey(loader, name)).get();
452 void release(qtexture_t *texture)
455 globalOutputStream() << "textures release: " << makeQuoted( texture->name ) << '\n';
457 m_qtextures.release(TextureKey(texture->load, texture->name));
460 void attach(TexturesCacheObserver &observer)
462 ASSERT_MESSAGE(m_observer == 0, "TexturesMap::attach: cannot attach observer");
463 m_observer = &observer;
466 void detach(TexturesCacheObserver &observer)
468 ASSERT_MESSAGE(m_observer == &observer, "TexturesMap::detach: cannot detach observer");
472 void realise(OpenGLBinding &GL)
474 if (--m_unrealised == 0) {
475 g_texture_globals.bTextureCompressionSupported = false;
477 if (GL.ARB_texture_compression()) {
478 g_texture_globals.bTextureCompressionSupported = true;
479 g_texture_globals.m_bOpenGLCompressionSupported = true;
482 if (GL.EXT_texture_compression_s3tc()) {
483 g_texture_globals.bTextureCompressionSupported = true;
484 g_texture_globals.m_bS3CompressionSupported = true;
487 switch (g_texture_globals.texture_components) {
490 case GL_COMPRESSED_RGBA_ARB:
491 if (!g_texture_globals.m_bOpenGLCompressionSupported) {
493 << "OpenGL extension GL_ARB_texture_compression not supported by current graphics drivers\n";
494 g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE;
495 g_texture_globals.texture_components = GL_RGBA;
498 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
499 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
500 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
501 if (!g_texture_globals.m_bS3CompressionSupported) {
503 << "OpenGL extension GL_EXT_texture_compression_s3tc not supported by current graphics drivers\n";
504 if (g_texture_globals.m_bOpenGLCompressionSupported) {
505 g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_RGBA;
506 g_texture_globals.texture_components = GL_COMPRESSED_RGBA_ARB;
508 g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE;
509 g_texture_globals.texture_components = GL_RGBA;
514 globalOutputStream() << "Unknown texture compression selected, reverting\n";
515 g_texture_globals.m_nTextureCompressionFormat = TEXTURECOMPRESSION_NONE;
516 g_texture_globals.texture_components = GL_RGBA;
521 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
522 if (max_tex_size == 0) {
526 for (qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i) {
527 if (!(*i).value.empty()) {
528 qtexture_realise(GL, *(*i).value, (*i).key);
531 if (m_observer != 0) {
532 m_observer->realise();
537 void unrealise(OpenGLBinding &GL)
539 if (++m_unrealised == 1) {
540 if (m_observer != 0) {
541 m_observer->unrealise();
543 for (qtextures_t::iterator i = m_qtextures.begin(); i != m_qtextures.end(); ++i) {
544 if (!(*i).value.empty()) {
545 qtexture_unrealise(GL, *(*i).value);
553 return m_unrealised == 0;
557 TexturesMap *g_texturesmap;
559 TexturesCache &GetTexturesCache()
561 return *g_texturesmap;
565 void Textures_Realise(OpenGLBinding &GL)
567 g_texturesmap->realise(GL);
570 void Textures_Unrealise(OpenGLBinding &GL)
572 g_texturesmap->unrealise(GL);
576 Callback<void()> g_texturesModeChangedNotify;
578 void Textures_setModeChangedNotify(const Callback<void()> ¬ify)
580 g_texturesModeChangedNotify = notify;
583 void Textures_ModeChanged(OpenGLBinding &GL)
585 if (g_texturesmap->realised()) {
586 SetTexParameters(GL, g_texture_mode);
588 for (TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i) {
589 glBindTexture(GL_TEXTURE_2D, (*i).value->texture_number);
590 SetTexParameters(GL, g_texture_mode);
593 glBindTexture(GL_TEXTURE_2D, 0);
595 g_texturesModeChangedNotify();
598 void Textures_SetMode(OpenGLBinding &GL, ETexturesMode mode)
600 if (g_texture_mode != mode) {
601 g_texture_mode = mode;
603 Textures_ModeChanged(GL);
607 void Textures_setTextureComponents(OpenGLBinding &GL, GLint texture_components)
609 if (g_texture_globals.texture_components != texture_components) {
610 Textures_Unrealise(GL);
611 g_texture_globals.texture_components = texture_components;
612 Textures_Realise(GL);
616 void Textures_UpdateTextureCompressionFormat()
618 OpenGLBinding &GL = GlobalOpenGL();
619 GLint texture_components = GL_RGBA;
621 switch (g_texture_globals.m_nTextureCompressionFormat) {
622 case (TEXTURECOMPRESSION_NONE): {
623 texture_components = GL_RGBA;
626 case (TEXTURECOMPRESSION_RGBA): {
627 texture_components = GL_COMPRESSED_RGBA_ARB;
630 case (TEXTURECOMPRESSION_RGBA_S3TC_DXT1): {
631 texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
634 case (TEXTURECOMPRESSION_RGBA_S3TC_DXT3): {
635 texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
638 case (TEXTURECOMPRESSION_RGBA_S3TC_DXT5): {
639 texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
644 Textures_setTextureComponents(GL, texture_components);
647 struct TextureCompression {
648 static void Export(const TextureCompressionFormat &self, const Callback<void(int)> &returnz)
653 static void Import(TextureCompressionFormat &self, int value)
655 if (!g_texture_globals.m_bOpenGLCompressionSupported
656 && g_texture_globals.m_bS3CompressionSupported
662 self = TEXTURECOMPRESSION_NONE;
665 self = TEXTURECOMPRESSION_RGBA;
668 self = TEXTURECOMPRESSION_RGBA_S3TC_DXT1;
671 self = TEXTURECOMPRESSION_RGBA_S3TC_DXT3;
674 self = TEXTURECOMPRESSION_RGBA_S3TC_DXT5;
677 Textures_UpdateTextureCompressionFormat();
681 struct TextureGamma {
682 static void Export(const float &self, const Callback<void(float)> &returnz)
687 static void Import(float &self, float value)
689 OpenGLBinding &GL = GlobalOpenGL();
691 Textures_Unrealise(GL);
693 Textures_Realise(GL);
699 static void Export(const ETexturesMode &self, const Callback<void(int)> &returnz)
702 case eTextures_NEAREST:
705 case eTextures_NEAREST_MIPMAP_NEAREST:
708 case eTextures_LINEAR:
711 case eTextures_NEAREST_MIPMAP_LINEAR:
714 case eTextures_LINEAR_MIPMAP_NEAREST:
717 case eTextures_LINEAR_MIPMAP_LINEAR:
720 case eTextures_MAX_ANISOTROPY:
728 static void Import(ETexturesMode &self, int value)
730 OpenGLBinding &GL = GlobalOpenGL();
733 Textures_SetMode(GL, eTextures_NEAREST);
736 Textures_SetMode(GL, eTextures_NEAREST_MIPMAP_NEAREST);
739 Textures_SetMode(GL, eTextures_LINEAR);
742 Textures_SetMode(GL, eTextures_NEAREST_MIPMAP_LINEAR);
745 Textures_SetMode(GL, eTextures_LINEAR_MIPMAP_NEAREST);
748 Textures_SetMode(GL, eTextures_LINEAR_MIPMAP_LINEAR);
751 Textures_SetMode(GL, eTextures_MAX_ANISOTROPY);
756 void Textures_constructPreferences(PreferencesPage &page)
759 const char *percentages[] = {"12.5%", "25%", "50%", "100%",};
762 STRING_ARRAY_RANGE(percentages),
763 make_property(g_Textures_textureQuality)
771 make_property<TextureGamma>(g_texture_globals.fGamma)
774 const char *texture_mode[] = {"Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear",
777 "Texture Render Mode",
778 STRING_ARRAY_RANGE(texture_mode),
779 make_property<TextureMode>(g_texture_mode)
783 const char *compression_none[] = {"None"};
784 const char *compression_opengl[] = {"None", "OpenGL ARB"};
785 const char *compression_s3tc[] = {"None", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5"};
786 const char *compression_opengl_s3tc[] = {"None", "OpenGL ARB", "S3TC DXT1", "S3TC DXT3", "S3TC DXT5"};
787 StringArrayRange compression(
788 (g_texture_globals.m_bOpenGLCompressionSupported)
789 ? (g_texture_globals.m_bS3CompressionSupported)
790 ? STRING_ARRAY_RANGE(compression_opengl_s3tc)
791 : STRING_ARRAY_RANGE(compression_opengl)
792 : (g_texture_globals.m_bS3CompressionSupported)
793 ? STRING_ARRAY_RANGE(compression_s3tc)
794 : STRING_ARRAY_RANGE(compression_none)
797 "Hardware Texture Compression",
799 make_property<TextureCompression>(g_texture_globals.m_nTextureCompressionFormat)
804 void Textures_constructPage(PreferenceGroup &group)
806 PreferencesPage page(group.createPage("Textures", "Texture Settings"));
807 Textures_constructPreferences(page);
810 void Textures_registerPreferencesPage()
812 PreferencesDialog_addDisplayPage(makeCallbackF(Textures_constructPage));
815 struct TextureCompressionPreference {
816 static void Export(const Callback<void(int)> &returnz)
818 returnz(g_texture_globals.m_nTextureCompressionFormat);
821 static void Import(int value)
823 g_texture_globals.m_nTextureCompressionFormat = static_cast<TextureCompressionFormat>( value );
824 Textures_UpdateTextureCompressionFormat();
828 void Textures_Construct(OpenGLBinding &GL)
830 g_texturesmap = new TexturesMap;
832 GlobalPreferenceSystem().registerPreference("TextureCompressionFormat",
833 make_property_string<TextureCompressionPreference>());
834 GlobalPreferenceSystem().registerPreference("TextureFiltering",
835 make_property_string(reinterpret_cast<int &>( g_texture_mode )));
836 GlobalPreferenceSystem().registerPreference("TextureQuality",
837 make_property_string(g_Textures_textureQuality.m_latched));
838 GlobalPreferenceSystem().registerPreference("SI_Gamma", make_property_string(g_texture_globals.fGamma));
840 g_Textures_textureQuality.useLatched();
842 Textures_registerPreferencesPage();
844 Textures_ModeChanged(GL);
847 void Textures_Destroy()
849 delete g_texturesmap;
853 #include "modulesystem/modulesmap.h"
854 #include "modulesystem/singletonmodule.h"
855 #include "modulesystem/moduleregistry.h"
857 class TexturesDependencies :
858 public GlobalRadiantModuleRef,
859 public GlobalOpenGLModuleRef,
860 public GlobalPreferenceSystemModuleRef {
861 ImageModulesRef m_image_modules;
863 TexturesDependencies() :
864 m_image_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("texturetypes"))
868 ImageModules &getImageModules()
870 return m_image_modules.get();
875 TexturesCache *m_textures;
877 typedef TexturesCache Type;
879 STRING_CONSTANT(Name, "*");
883 OpenGLBinding &GL = GlobalOpenGL();
884 Textures_Construct(GL);
886 m_textures = &GetTexturesCache();
894 TexturesCache *getTable()
900 typedef SingletonModule<TexturesAPI, TexturesDependencies> TexturesModule;
901 typedef Static<TexturesModule> StaticTexturesModule;
902 StaticRegisterModule staticRegisterTextures(StaticTexturesModule::instance());
904 ImageModules &Textures_getImageModules()
906 return StaticTexturesModule::instance().getDependencies().getImageModules();