Coverage Report

Created: 2026-01-09 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreCompositor.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 "OgreCompositor.h"
30
#include "OgreHardwarePixelBuffer.h"
31
#include "OgreCompositorInstance.h"
32
33
namespace Ogre {
34
35
//-----------------------------------------------------------------------
36
Compositor::Compositor(ResourceManager* creator, const String& name, ResourceHandle handle, const String& group, bool isManual, ManualResourceLoader* loader):
37
0
    Resource(creator, name, handle, group, isManual, loader),
38
0
    mCompilationRequired(true)
39
0
{
40
0
}
41
//-----------------------------------------------------------------------
42
43
Compositor::~Compositor()
44
0
{
45
0
    removeAllTechniques();
46
    // have to call this here reather than in Resource destructor
47
    // since calling virtual methods in base destructors causes crash
48
0
    unload();
49
0
}
50
//-----------------------------------------------------------------------
51
CompositionTechnique *Compositor::createTechnique()
52
0
{
53
0
    CompositionTechnique *t = OGRE_NEW CompositionTechnique(this);
54
0
    mTechniques.push_back(t);
55
0
    mCompilationRequired = true;
56
0
    return t;
57
0
}
58
//-----------------------------------------------------------------------
59
60
void Compositor::removeTechnique(size_t index)
61
0
{
62
0
    assert (index < mTechniques.size() && "Index out of bounds.");
63
0
    Techniques::iterator i = mTechniques.begin() + index;
64
0
    OGRE_DELETE (*i);
65
0
    mTechniques.erase(i);
66
0
    mSupportedTechniques.clear();
67
0
    mCompilationRequired = true;
68
0
}
69
//-----------------------------------------------------------------------
70
void Compositor::removeAllTechniques()
71
0
{
72
0
    for (auto *t : mTechniques)
73
0
    {
74
0
        OGRE_DELETE t;
75
0
    }
76
0
    mTechniques.clear();
77
0
    mSupportedTechniques.clear();
78
0
    mCompilationRequired = true;
79
0
}
80
//-----------------------------------------------------------------------
81
Compositor::TechniqueIterator Compositor::getTechniqueIterator(void)
82
0
{
83
0
    return TechniqueIterator(mTechniques.begin(), mTechniques.end());
84
0
}
85
//-----------------------------------------------------------------------
86
87
Compositor::TechniqueIterator Compositor::getSupportedTechniqueIterator(void)
88
0
{
89
0
    return TechniqueIterator(mSupportedTechniques.begin(), mSupportedTechniques.end());
90
0
}
91
//-----------------------------------------------------------------------
92
void Compositor::loadImpl(void)
93
0
{
94
    // compile if required
95
0
    if (mCompilationRequired)
96
0
        compile();
97
98
0
    createGlobalTextures();
99
0
}
100
//-----------------------------------------------------------------------
101
void Compositor::unloadImpl(void)
102
0
{
103
0
    freeGlobalTextures();
104
0
}
105
//-----------------------------------------------------------------------
106
size_t Compositor::calculateSize(void) const
107
0
{
108
0
    return 0;
109
0
}
110
111
//-----------------------------------------------------------------------
112
void Compositor::compile()
113
0
{
114
    /// Sift out supported techniques
115
0
    mSupportedTechniques.clear();
116
117
0
    for (auto t : mTechniques)
118
0
    {
119
        // Allow texture support with degraded pixel format
120
0
        if (t->isSupported(true))
121
0
        {
122
0
            mSupportedTechniques.push_back(t);
123
0
        }
124
0
    }
125
126
0
    if (mSupportedTechniques.empty())
127
0
        LogManager::getSingleton().logError("Compositor '" + getName() + "' has no supported techniques");
128
129
0
    mCompilationRequired = false;
130
0
}
131
//---------------------------------------------------------------------
132
CompositionTechnique* Compositor::getSupportedTechnique(const String& schemeName)
133
0
{
134
0
    for(auto & t : mSupportedTechniques)
135
0
    {
136
0
        if (t->getSchemeName() == schemeName)
137
0
        {
138
0
            return t;
139
0
        }
140
0
    }
141
142
    // didn't find a matching one
143
0
    for(auto & t : mSupportedTechniques)
144
0
    {
145
0
        if (t->getSchemeName().empty())
146
0
        {
147
0
            return t;
148
0
        }
149
0
    }
150
151
0
    return 0;
152
153
0
}
154
155
TexturePtr createTexture(const String& name, const CompositionTechnique::TextureDefinition& def, PixelFormat pf,
156
                         const String& fsaaHint)
157
0
{
158
0
    bool hwGamma = def.hwGammaWrite && !PixelUtil::isFloatingPoint(pf);
159
0
    return TextureManager::getSingleton().createManual(name, RGN_INTERNAL, def.type, def.width, def.height, def.depth,
160
0
                                                       0, pf, TU_RENDERTARGET, 0, hwGamma, def.fsaa, fsaaHint);
161
0
}
162
163
//-----------------------------------------------------------------------
164
void Compositor::createGlobalTextures()
165
0
{
166
0
    if (mSupportedTechniques.empty())
167
0
        return;
168
169
    //To make sure that we are consistent, it is demanded that all composition
170
    //techniques define the same set of global textures.
171
0
    typedef std::set<String> StringSet;
172
0
    StringSet globalTextureNames;
173
174
    //Initialize global textures from first supported technique
175
0
    CompositionTechnique* firstTechnique = mSupportedTechniques[0];
176
177
0
    for (auto *def : firstTechnique->getTextureDefinitions())
178
0
    {
179
0
        if (def->scope == CompositionTechnique::TS_GLOBAL)
180
0
        {
181
            //Check that this is a legit global texture
182
0
            OgreAssert(def->refCompName.empty(), "Global compositor texture definition can not be a reference");
183
0
            OgreAssert(def->width && def->height, "Global compositor texture definition must have absolute size");
184
0
            if (def->pooled)
185
0
            {
186
0
                LogManager::getSingleton().logWarning(mName+" - pooling global compositor textures has no effect");
187
0
            }
188
0
            globalTextureNames.insert(def->name);
189
190
            //TODO GSOC : Heavy copy-pasting from CompositorInstance. How to we solve it?
191
192
            // unique, even without dummyCounter, as these are global
193
0
            String baseName = StringUtil::format("%s.%s", def->name.c_str(), mName.c_str());
194
195
            /// Make the tetxure
196
0
            RenderTarget* rendTarget;
197
0
            if (def->formatList.size() > 1)
198
0
            {
199
0
                MultiRenderTarget* mrt = Root::getSingleton().getRenderSystem()->createMultiRenderTarget(baseName);
200
0
                mGlobalMRTs[def->name] = mrt;
201
202
                // create and bind individual surfaces
203
0
                uint8 atch = 0;
204
0
                for (auto p : def->formatList)
205
0
                {
206
207
0
                    String texname = StringUtil::format("mrt%d.%s", atch, baseName.c_str());
208
0
                    TexturePtr tex = createTexture(texname, *def, p);
209
210
0
                    RenderTexture* rt = tex->getBuffer()->getRenderTarget();
211
0
                    rt->setAutoUpdated(false);
212
0
                    mrt->bindSurface(atch, rt);
213
214
                    // Also add to local textures so we can look up
215
0
                    String mrtLocalName = CompositorInstance::getMRTTexLocalName(def->name, atch);
216
0
                    mGlobalTextures[mrtLocalName] = tex;
217
0
                    atch++;
218
0
                }
219
220
0
                rendTarget = mrt;
221
0
            }
222
0
            else
223
0
            {
224
0
                String texName = baseName;
225
226
                // space in the name mixup the cegui in the compositor demo
227
                // this is an auto generated name - so no spaces can't hart us.
228
0
                std::replace( texName.begin(), texName.end(), ' ', '_' );
229
230
0
                TexturePtr tex = createTexture(texName, *def, def->formatList[0]);
231
0
                rendTarget = tex->getBuffer()->getRenderTarget();
232
0
                mGlobalTextures[def->name] = tex;
233
0
            }
234
235
0
            rendTarget->setAutoUpdated( false );
236
237
            //Set DepthBuffer pool for sharing
238
0
            if(rendTarget->getDepthBufferPool() != RBP_NONE)
239
0
                rendTarget->setDepthBufferPool( def->depthBufferId );
240
0
        }
241
0
    }
242
243
    //Validate that all other supported techniques expose the same set of global textures.
244
0
    for (size_t i = 1; i < mSupportedTechniques.size(); i++)
245
0
    {
246
0
        bool isConsistent = true;
247
0
        size_t numGlobals = 0;
248
0
        CompositionTechnique* technique = mSupportedTechniques[i];
249
0
        for (auto *texDef : technique->getTextureDefinitions())
250
0
        {
251
0
            if (texDef->scope == CompositionTechnique::TS_GLOBAL)
252
0
            {
253
0
                if (globalTextureNames.find(texDef->name) == globalTextureNames.end())
254
0
                {
255
0
                    isConsistent = false;
256
0
                    break;
257
0
                }
258
0
                numGlobals++;
259
0
            }
260
0
        }
261
0
        if (numGlobals != globalTextureNames.size())
262
0
            isConsistent = false;
263
264
0
        OgreAssert(isConsistent, "Different composition techniques define different global textures");
265
0
    }
266
267
0
}
268
//-----------------------------------------------------------------------
269
void Compositor::freeGlobalTextures()
270
0
{
271
0
    for (const auto& t : mGlobalTextures)
272
0
    {
273
0
        TextureManager::getSingleton().remove(t.second);
274
0
    }
275
0
    mGlobalTextures.clear();
276
277
0
    for (const auto& m : mGlobalMRTs)
278
0
    {
279
        // remove MRT
280
0
        Root::getSingleton().getRenderSystem()->destroyRenderTarget(m.second->getName());
281
0
    }
282
0
    mGlobalMRTs.clear();
283
284
0
}
285
//-----------------------------------------------------------------------
286
const String& Compositor::getTextureInstanceName(const String& name, size_t mrtIndex)
287
0
{
288
0
    return getTextureInstance(name, mrtIndex)->getName();
289
0
}
290
//-----------------------------------------------------------------------
291
const TexturePtr& Compositor::getTextureInstance(const String& name, size_t mrtIndex)
292
0
{
293
    //Try simple texture
294
0
    GlobalTextureMap::iterator i = mGlobalTextures.find(name);
295
0
    if(i != mGlobalTextures.end())
296
0
    {
297
0
        return i->second;
298
0
    }
299
    //Try MRT
300
0
    String mrtName = CompositorInstance::getMRTTexLocalName(name, mrtIndex);
301
0
    i = mGlobalTextures.find(mrtName);
302
0
    if(i != mGlobalTextures.end())
303
0
    {
304
0
        return i->second;
305
0
    }
306
307
0
    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Non-existent global texture name");
308
309
0
}
310
//---------------------------------------------------------------------
311
RenderTarget* Compositor::getRenderTarget(const String& name, int slice)
312
0
{
313
    // try simple texture
314
0
    GlobalTextureMap::iterator i = mGlobalTextures.find(name);
315
0
    if(i != mGlobalTextures.end())
316
0
        return i->second->getRenderTarget(slice);
317
318
    // try MRTs
319
0
    GlobalMRTMap::iterator mi = mGlobalMRTs.find(name);
320
0
    if (mi != mGlobalMRTs.end())
321
0
        return mi->second;
322
323
0
    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Non-existent global texture name");
324
0
}
325
//---------------------------------------------------------------------
326
}