Coverage Report

Created: 2026-08-29 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreTextureManager.cpp
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#include "OgreStableHeaders.h"
29
#include "OgrePixelFormat.h"
30
31
namespace Ogre {
32
    //-----------------------------------------------------------------------
33
    template<> TextureManager* Singleton<TextureManager>::msSingleton = 0;
34
    TextureManager* TextureManager::getSingletonPtr(void)
35
0
    {
36
0
        return msSingleton;
37
0
    }
38
    TextureManager& TextureManager::getSingleton(void)
39
0
    {  
40
0
        assert( msSingleton );  return ( *msSingleton );  
41
0
    }
42
    //-----------------------------------------------------------------------
43
    TextureManager::TextureManager(void)
44
0
         : mPreferredIntegerBitDepth(0)
45
0
         , mPreferredFloatBitDepth(0)
46
0
         , mDefaultNumMipmaps(MIP_UNLIMITED)
47
0
    {
48
0
        mResourceType = "Texture";
49
0
        mLoadOrder = 75.0f;
50
51
        // Subclasses should register (when this is fully constructed)
52
0
    }
53
    //-----------------------------------------------------------------------
54
    TextureManager::~TextureManager()
55
0
    {
56
        // subclasses should unregister with resource group manager
57
58
0
    }
59
    SamplerPtr TextureManager::createSampler(const String& name)
60
0
    {
61
0
        SamplerPtr ret = _createSamplerImpl();
62
0
        if(!name.empty())
63
0
        {
64
0
            if (mNamedSamplers.find(name) != mNamedSamplers.end())
65
0
                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Sampler '" + name + "' already exists");
66
0
            mNamedSamplers[name] = ret;
67
0
        }
68
0
        return ret;
69
0
    }
70
71
    /// retrieve an named sampler
72
    const SamplerPtr& TextureManager::getSampler(const String& name) const
73
0
    {
74
0
        static SamplerPtr nullPtr;
75
0
        auto it = mNamedSamplers.find(name);
76
0
        if(it == mNamedSamplers.end())
77
0
            return nullPtr;
78
0
        return it->second;
79
0
    }
80
    //-----------------------------------------------------------------------
81
    TexturePtr TextureManager::getByName(const String& name, const String& groupName) const
82
0
    {
83
0
        return static_pointer_cast<Texture>(getResourceByName(name, groupName));
84
0
    }
85
    //-----------------------------------------------------------------------
86
    TexturePtr TextureManager::create (const String& name, const String& group,
87
                                    bool isManual, ManualResourceLoader* loader,
88
                                    const NameValuePairList* createParams)
89
0
    {
90
0
        return static_pointer_cast<Texture>(createResource(name,group,isManual,loader,createParams));
91
0
    }
92
    //-----------------------------------------------------------------------
93
    TextureManager::ResourceCreateOrRetrieveResult TextureManager::createOrRetrieve(
94
            const String &name, const String& group, bool isManual, ManualResourceLoader* loader,
95
            const NameValuePairList* createParams, TextureType texType, int numMipmaps, Real gamma,
96
            bool isAlpha, PixelFormat desiredFormat, bool hwGamma)
97
0
    {
98
0
        ResourceCreateOrRetrieveResult res =
99
0
            Ogre::ResourceManager::createOrRetrieve(name, group, isManual, loader, createParams);
100
        // Was it created?
101
0
        if(res.second)
102
0
        {
103
0
            TexturePtr tex = static_pointer_cast<Texture>(res.first);
104
0
            tex->setTextureType(texType);
105
0
            tex->setNumMipmaps((numMipmaps == MIP_DEFAULT)? mDefaultNumMipmaps :
106
0
                static_cast<uint32>(numMipmaps));
107
0
            tex->setGamma(gamma);
108
0
            OGRE_IGNORE_DEPRECATED_BEGIN
109
0
            tex->setTreatLuminanceAsAlpha(isAlpha);
110
0
            OGRE_IGNORE_DEPRECATED_END
111
0
            tex->setFormat(desiredFormat);
112
0
            tex->setHardwareGammaEnabled(hwGamma);
113
0
        }
114
0
        return res;
115
0
    }
116
    //-----------------------------------------------------------------------
117
    TexturePtr TextureManager::prepare(const String &name, const String& group, TextureType texType,
118
                                       int numMipmaps, Real gamma, bool isAlpha,
119
                                       PixelFormat desiredFormat, bool hwGamma)
120
0
    {
121
0
        ResourceCreateOrRetrieveResult res =
122
0
            createOrRetrieve(name,group,false,0,0,texType,numMipmaps,gamma,isAlpha,desiredFormat,hwGamma);
123
0
        TexturePtr tex = static_pointer_cast<Texture>(res.first);
124
0
        tex->prepare();
125
0
        return tex;
126
0
    }
127
    //-----------------------------------------------------------------------
128
    TexturePtr TextureManager::load(const String& name, const String& group, TextureType texType,
129
                                    int numMipmaps, Real gamma, bool isAlpha, PixelFormat desiredFormat,
130
                                    bool hwGamma)
131
0
    {
132
0
        auto res = createOrRetrieve(name, group, false, 0, 0, texType, numMipmaps, gamma, isAlpha,
133
0
                                    desiredFormat, hwGamma);
134
0
        TexturePtr tex = static_pointer_cast<Texture>(res.first);
135
0
        tex->load();
136
0
        return tex;
137
0
    }
138
    TexturePtr TextureManager::load(const String& name, const String& group, TextureType texType,
139
                                    int numMipmaps, Real gamma, PixelFormat desiredFormat, bool hwGamma)
140
0
    {
141
0
        auto res = createOrRetrieve(name, group, false, 0, 0, texType, numMipmaps, gamma, false,
142
0
                                    desiredFormat, hwGamma);
143
0
        TexturePtr tex = static_pointer_cast<Texture>(res.first);
144
0
        tex->load();
145
0
        return tex;
146
0
    }
147
    //-----------------------------------------------------------------------
148
    TexturePtr TextureManager::loadImage( const String &name, const String& group,
149
        const Image &img, TextureType texType, int numMipmaps, Real gamma, bool isAlpha, 
150
        PixelFormat desiredFormat, bool hwGamma)
151
0
    {
152
0
        TexturePtr tex = create(name, group, true);
153
154
0
        tex->setTextureType(texType);
155
0
        tex->setNumMipmaps((numMipmaps == MIP_DEFAULT)? mDefaultNumMipmaps :
156
0
            static_cast<uint32>(numMipmaps));
157
0
        tex->setGamma(gamma);
158
0
        OGRE_IGNORE_DEPRECATED_BEGIN
159
0
        tex->setTreatLuminanceAsAlpha(isAlpha);
160
0
        OGRE_IGNORE_DEPRECATED_END
161
0
        tex->setFormat(desiredFormat);
162
0
        tex->setHardwareGammaEnabled(hwGamma);
163
0
        tex->loadImage(img);
164
165
0
        return tex;
166
0
    }
167
    //-----------------------------------------------------------------------
168
    TexturePtr TextureManager::loadRawData(const String &name, const String& group,
169
        DataStreamPtr& stream, ushort uWidth, ushort uHeight, 
170
        PixelFormat format, TextureType texType, 
171
        int numMipmaps, Real gamma, bool hwGamma)
172
0
    {
173
0
        TexturePtr tex = create(name, group, true);
174
175
0
        tex->setTextureType(texType);
176
0
        tex->setNumMipmaps((numMipmaps == MIP_DEFAULT)? mDefaultNumMipmaps :
177
0
            static_cast<uint32>(numMipmaps));
178
0
        tex->setGamma(gamma);
179
0
        tex->setHardwareGammaEnabled(hwGamma);
180
0
        tex->loadRawData(stream, uWidth, uHeight, format);
181
        
182
0
        return tex;
183
0
    }
184
    //-----------------------------------------------------------------------
185
    TexturePtr TextureManager::createManual(const String & name, const String& group,
186
        TextureType texType, uint width, uint height, uint depth, int numMipmaps,
187
        PixelFormat format, int usage, ManualResourceLoader* loader, bool hwGamma, 
188
        uint fsaa, const String& fsaaHint)
189
0
    {
190
0
        TexturePtr ret;
191
192
0
        OgreAssert(width && height && depth, "total size of texture must not be zero");
193
194
        // Check for texture support
195
0
        const auto caps = Root::getSingleton().getRenderSystem()->getCapabilities();
196
0
        if (((texType == TEX_TYPE_3D) && !caps->hasCapability(RSC_TEXTURE_3D)) ||
197
0
            ((texType == TEX_TYPE_2D_ARRAY) && !caps->hasCapability(RSC_TEXTURE_2D_ARRAY)))
198
0
            return ret;
199
200
0
        ret = create(name, group, true, loader);
201
202
0
        if(!ret)
203
0
            return ret;
204
205
0
        ret->setTextureType(texType);
206
0
        ret->setWidth(width);
207
0
        ret->setHeight(height);
208
0
        ret->setDepth(depth);
209
0
        ret->setNumMipmaps((numMipmaps == MIP_DEFAULT)? mDefaultNumMipmaps :
210
0
            static_cast<uint32>(numMipmaps));
211
0
        ret->setFormat(format);
212
0
        ret->setUsage(usage);
213
0
        ret->setHardwareGammaEnabled(hwGamma);
214
0
        ret->setFSAA(fsaa, fsaaHint);
215
0
        ret->createInternalResources();
216
0
        return ret;
217
0
    }
218
    //-----------------------------------------------------------------------
219
    void TextureManager::setPreferredIntegerBitDepth(ushort bits, bool reloadTextures)
220
0
    {
221
0
        mPreferredIntegerBitDepth = bits;
222
223
0
        if (reloadTextures)
224
0
        {
225
            // Iterate through all textures
226
0
            for (auto & r : mResources)
227
0
            {
228
0
                Texture* texture = static_cast<Texture*>(r.second.get());
229
                // Reload loaded and reloadable texture only
230
0
                if (texture->isLoaded() && texture->isReloadable())
231
0
                {
232
0
                    texture->unload();
233
0
                    texture->setDesiredIntegerBitDepth(bits);
234
0
                    texture->load();
235
0
                }
236
0
                else
237
0
                {
238
0
                    texture->setDesiredIntegerBitDepth(bits);
239
0
                }
240
0
            }
241
0
        }
242
0
    }
243
    //-----------------------------------------------------------------------
244
    ushort TextureManager::getPreferredIntegerBitDepth(void) const
245
0
    {
246
0
        return mPreferredIntegerBitDepth;
247
0
    }
248
    //-----------------------------------------------------------------------
249
    void TextureManager::setPreferredFloatBitDepth(ushort bits, bool reloadTextures)
250
0
    {
251
0
        mPreferredFloatBitDepth = bits;
252
253
0
        if (reloadTextures)
254
0
        {
255
            // Iterate through all textures
256
0
            for (auto & r : mResources)
257
0
            {
258
0
                Texture* texture = static_cast<Texture*>(r.second.get());
259
                // Reload loaded and reloadable texture only
260
0
                if (texture->isLoaded() && texture->isReloadable())
261
0
                {
262
0
                    texture->unload();
263
0
                    texture->setDesiredFloatBitDepth(bits);
264
0
                    texture->load();
265
0
                }
266
0
                else
267
0
                {
268
0
                    texture->setDesiredFloatBitDepth(bits);
269
0
                }
270
0
            }
271
0
        }
272
0
    }
273
    //-----------------------------------------------------------------------
274
    ushort TextureManager::getPreferredFloatBitDepth(void) const
275
0
    {
276
0
        return mPreferredFloatBitDepth;
277
0
    }
278
    //-----------------------------------------------------------------------
279
    void TextureManager::setPreferredBitDepths(ushort integerBits, ushort floatBits, bool reloadTextures)
280
0
    {
281
0
        mPreferredIntegerBitDepth = integerBits;
282
0
        mPreferredFloatBitDepth = floatBits;
283
284
0
        if (reloadTextures)
285
0
        {
286
            // Iterate through all textures
287
0
            for (auto & r : mResources)
288
0
            {
289
0
                Texture* texture = static_cast<Texture*>(r.second.get());
290
                // Reload loaded and reloadable texture only
291
0
                if (texture->isLoaded() && texture->isReloadable())
292
0
                {
293
0
                    texture->unload();
294
0
                    texture->setDesiredBitDepths(integerBits, floatBits);
295
0
                    texture->load();
296
0
                }
297
0
                else
298
0
                {
299
0
                    texture->setDesiredBitDepths(integerBits, floatBits);
300
0
                }
301
0
            }
302
0
        }
303
0
    }
304
    //-----------------------------------------------------------------------
305
    void TextureManager::setDefaultNumMipmaps( uint32 num )
306
0
    {
307
0
        mDefaultNumMipmaps = num;
308
0
    }
309
    //-----------------------------------------------------------------------
310
    bool TextureManager::isFormatSupported(TextureType ttype, PixelFormat format, int usage)
311
0
    {
312
0
        return getNativeFormat(ttype, format, usage) == format;
313
0
    }
314
    //-----------------------------------------------------------------------
315
    bool TextureManager::isEquivalentFormatSupported(TextureType ttype, PixelFormat format, int usage)
316
0
    {
317
0
        PixelFormat supportedFormat = getNativeFormat(ttype, format, usage);
318
319
        // Assume that same or greater number of bits means quality not degraded
320
0
        return PixelUtil::getNumElemBits(supportedFormat) >= PixelUtil::getNumElemBits(format);
321
        
322
0
    }
323
324
    bool TextureManager::isHardwareFilteringSupported(TextureType ttype, PixelFormat format,
325
                                                      int usage, bool preciseFormatOnly)
326
0
    {
327
0
        if (format == PF_UNKNOWN)
328
0
            return false;
329
330
        // Check native format
331
0
        if (preciseFormatOnly && !isFormatSupported(ttype, format, usage))
332
0
            return false;
333
334
0
        return true;
335
0
    }
336
337
    const TexturePtr& TextureManager::_getWarningTexture()
338
0
    {
339
0
        if(mWarningTexture)
340
0
            return mWarningTexture;
341
342
        // Generate warning texture
343
0
        Image pixels(PF_R5G6B5, 8, 8);
344
345
        // Yellow/black stripes
346
0
        const ColourValue black(0, 0, 0), yellow(1, 1, 0);
347
0
        for (uint32 y = 0; y < pixels.getHeight(); ++y)
348
0
        {
349
0
            for (uint32 x = 0; x < pixels.getWidth(); ++x)
350
0
            {
351
0
                pixels.setColourAt((((x + y) % 8) < 4) ? black : yellow, x, y, 0);
352
0
            }
353
0
        }
354
355
0
        mWarningTexture = loadImage("Warning", RGN_INTERNAL, pixels);
356
357
0
        return mWarningTexture;
358
0
    }
359
360
    const SamplerPtr& TextureManager::getDefaultSampler()
361
0
    {
362
0
        if(!mDefaultSampler)
363
0
            mDefaultSampler = createSampler();
364
365
0
        return mDefaultSampler;
366
0
    }
367
}