Coverage Report

Created: 2026-05-30 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreRenderSystem.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 "OgrePrerequisites.h"
29
#include "OgreStableHeaders.h"
30
// RenderSystem implementation
31
// Note that most of this class is abstract since
32
//  we cannot know how to implement the behaviour without
33
//  being aware of the 3D API. However there are a few
34
//  simple functions which can have a base implementation
35
36
#include "OgreHardwareOcclusionQuery.h"
37
#include "OgreComponents.h"
38
39
#ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
40
#include "OgreRTShaderConfig.h"
41
#endif
42
43
namespace Ogre {
44
45
    RenderSystem::Listener* RenderSystem::msSharedEventListener = 0;
46
47
    static const TexturePtr sNullTexPtr;
48
49
    //-----------------------------------------------------------------------
50
    RenderSystem::RenderSystem()
51
0
        : mActiveRenderTarget(0)
52
0
        , mTextureManager(0)
53
0
        , mActiveViewport(0)
54
        // This means CULL clockwise vertices, i.e. front of poly is counter-clockwise
55
        // This makes it the same as OpenGL and other right-handed systems
56
0
        , mCullingMode(CULL_CLOCKWISE)
57
0
        , mBatchCount(0)
58
0
        , mFaceCount(0)
59
0
        , mVertexCount(0)
60
0
        , mInvertVertexWinding(false)
61
0
        , mIsReverseDepthBufferEnabled(false)
62
0
        , mDisabledTexUnitsFrom(0)
63
0
        , mCurrentPassIterationCount(0)
64
0
        , mCurrentPassIterationNum(0)
65
0
        , mDerivedDepthBias(false)
66
0
        , mDerivedDepthBiasBase(0.0f)
67
0
        , mDerivedDepthBiasMultiplier(0.0f)
68
0
        , mDerivedDepthBiasSlopeScale(0.0f)
69
0
        , mClipPlanesDirty(true)
70
0
        , mRealCapabilities(0)
71
0
        , mCurrentCapabilities(0)
72
0
        , mUseCustomCapabilities(false)
73
0
        , mNativeShadingLanguageVersion(0)
74
0
        , mTexProjRelative(false)
75
0
        , mTexProjRelativeOrigin(Vector3::ZERO)
76
0
    {
77
0
        mEventNames.push_back("RenderSystemCapabilitiesCreated");
78
0
    }
79
80
    void RenderSystem::initFixedFunctionParams()
81
0
    {
82
0
        if(mFixedFunctionParams)
83
0
            return;
84
85
0
        GpuLogicalBufferStructPtr logicalBufferStruct(new GpuLogicalBufferStruct());
86
0
        mFixedFunctionParams.reset(new GpuProgramParameters);
87
0
        mFixedFunctionParams->_setLogicalIndexes(logicalBufferStruct);
88
0
        mFixedFunctionParams->setAutoConstant(0, GpuProgramParameters::ACT_WORLD_MATRIX);
89
0
        mFixedFunctionParams->setAutoConstant(4, GpuProgramParameters::ACT_VIEW_MATRIX);
90
0
        mFixedFunctionParams->setAutoConstant(8, GpuProgramParameters::ACT_PROJECTION_MATRIX);
91
0
        mFixedFunctionParams->setAutoConstant(12, GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
92
0
        mFixedFunctionParams->setAutoConstant(13, GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
93
0
        mFixedFunctionParams->setAutoConstant(14, GpuProgramParameters::ACT_SURFACE_SPECULAR_COLOUR);
94
0
        mFixedFunctionParams->setAutoConstant(15, GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
95
0
        mFixedFunctionParams->setAutoConstant(16, GpuProgramParameters::ACT_SURFACE_SHININESS);
96
0
        mFixedFunctionParams->setAutoConstant(17, GpuProgramParameters::ACT_POINT_PARAMS);
97
0
        mFixedFunctionParams->setConstant(18, Vector4::ZERO); // ACT_FOG_PARAMS
98
0
        mFixedFunctionParams->setConstant(19, Vector4::ZERO); // ACT_FOG_COLOUR
99
0
        mFixedFunctionParams->setAutoConstant(20, GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
100
101
        // allocate per light parameters. slots 21..69
102
0
        for(int i = 0; i < OGRE_MAX_SIMULTANEOUS_LIGHTS; i++)
103
0
        {
104
0
            size_t light_offset = 21 + i * 6;
105
0
            mFixedFunctionParams->setConstant(light_offset + 0, Vector4::ZERO); // position
106
0
            mFixedFunctionParams->setConstant(light_offset + 1, Vector4::ZERO); // direction
107
0
            mFixedFunctionParams->setConstant(light_offset + 2, Vector4::ZERO); // diffuse
108
0
            mFixedFunctionParams->setConstant(light_offset + 3, Vector4::ZERO); // specular
109
0
            mFixedFunctionParams->setConstant(light_offset + 4, Vector4::ZERO); // attenuation
110
0
            mFixedFunctionParams->setConstant(light_offset + 5, Vector4::ZERO); // spotlight
111
0
        }
112
0
    }
113
114
    void RenderSystem::setFFPLightParams(uint32 index, bool enabled)
115
0
    {
116
0
        if(!mFixedFunctionParams)
117
0
            return;
118
119
0
        size_t light_offset = 21 + 6 * index;
120
0
        if (!enabled)
121
0
        {
122
0
            mFixedFunctionParams->clearAutoConstant(light_offset + 0);
123
0
            mFixedFunctionParams->clearAutoConstant(light_offset + 1);
124
0
            mFixedFunctionParams->clearAutoConstant(light_offset + 2);
125
0
            mFixedFunctionParams->clearAutoConstant(light_offset + 3);
126
0
            mFixedFunctionParams->clearAutoConstant(light_offset + 4);
127
0
            mFixedFunctionParams->clearAutoConstant(light_offset + 5);
128
0
            return;
129
0
        }
130
0
        mFixedFunctionParams->setAutoConstant(light_offset + 0, GpuProgramParameters::ACT_LIGHT_POSITION, index);
131
0
        mFixedFunctionParams->setAutoConstant(light_offset + 1, GpuProgramParameters::ACT_LIGHT_DIRECTION, index);
132
0
        mFixedFunctionParams->setAutoConstant(light_offset + 2, GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, index);
133
0
        mFixedFunctionParams->setAutoConstant(light_offset + 3, GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, index);
134
0
        mFixedFunctionParams->setAutoConstant(light_offset + 4, GpuProgramParameters::ACT_LIGHT_ATTENUATION, index);
135
0
        mFixedFunctionParams->setAutoConstant(light_offset + 5, GpuProgramParameters::ACT_SPOTLIGHT_PARAMS, index);
136
0
    }
137
138
    const HardwareBufferPtr& RenderSystem::updateDefaultUniformBuffer(GpuProgramType gptype, const ConstantList& params)
139
0
    {
140
0
        auto& ubo = mUniformBuffer[gptype];
141
0
        if (!ubo || ubo->getSizeInBytes() < params.size())
142
0
        {
143
0
            ubo = HardwareBufferManager::getSingleton().createUniformBuffer(params.size());
144
0
        }
145
146
0
        ubo->writeData(0, params.size(), params.data(), true);
147
148
0
        return ubo;
149
0
    }
150
    //-----------------------------------------------------------------------
151
    RenderSystem::~RenderSystem()
152
0
    {
153
0
        shutdown();
154
0
        OGRE_DELETE mRealCapabilities;
155
0
        mRealCapabilities = 0;
156
        // Current capabilities managed externally
157
0
        mCurrentCapabilities = 0;
158
0
    }
159
160
    RenderWindowDescription RenderSystem::getRenderWindowDescription() const
161
0
    {
162
0
        RenderWindowDescription ret;
163
0
        auto& miscParams = ret.miscParams;
164
165
0
        auto end = mOptions.end();
166
167
0
        auto opt = mOptions.find("Full Screen");
168
0
        if (opt == end)
169
0
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Can't find 'Full Screen' option");
170
171
0
        ret.useFullScreen = StringConverter::parseBool(opt->second.currentValue);
172
173
0
        opt = mOptions.find("Video Mode");
174
0
        if (opt == end)
175
0
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Can't find 'Video Mode' option");
176
177
0
        StringStream mode(opt->second.currentValue);
178
0
        String token;
179
180
0
        mode >> ret.width;
181
0
        mode >> token; // 'x' as seperator between width and height
182
0
        mode >> ret.height;
183
184
        // backend specific options. Presence determined by getConfigOptions
185
0
        mode >> token; // '@' as seperator between bpp on D3D
186
0
        if(!mode.eof())
187
0
        {
188
0
            uint32 bpp;
189
0
            mode >> bpp;
190
0
            miscParams.emplace("colourDepth", std::to_string(bpp));
191
0
        }
192
193
0
        if((opt = mOptions.find("FSAA")) != end)
194
0
        {
195
0
            StringStream fsaaMode(opt->second.currentValue);
196
0
            uint32_t fsaa;
197
0
            fsaaMode >> fsaa;
198
0
            miscParams.emplace("FSAA", std::to_string(fsaa));
199
200
            // D3D specific
201
0
            if(!fsaaMode.eof())
202
0
            {
203
0
                String hint;
204
0
                fsaaMode >> hint;
205
0
                miscParams.emplace("FSAAHint", hint);
206
0
            }
207
0
        }
208
209
0
        if((opt = mOptions.find("VSync")) != end)
210
0
            miscParams.emplace("vsync", opt->second.currentValue);
211
212
0
        if((opt = mOptions.find("sRGB Gamma Conversion")) != end)
213
0
            miscParams.emplace("gamma", opt->second.currentValue);
214
215
0
        if((opt = mOptions.find("HDR Display")) != end)
216
0
            miscParams.emplace("hdrDisplay", opt->second.currentValue);
217
218
0
        if((opt = mOptions.find("Colour Depth")) != end)
219
0
            miscParams.emplace("colourDepth", opt->second.currentValue);
220
221
0
        if((opt = mOptions.find("VSync Interval")) != end)
222
0
            miscParams.emplace("vsyncInterval", opt->second.currentValue);
223
224
0
        if((opt = mOptions.find("Display Frequency")) != end)
225
0
            miscParams.emplace("displayFrequency", opt->second.currentValue);
226
227
0
        if((opt = mOptions.find("Content Scaling Factor")) != end)
228
0
            miscParams["contentScalingFactor"] = opt->second.currentValue;
229
230
0
        if((opt = mOptions.find("Rendering Device")) != end)
231
0
        {
232
            // try to parse "Monitor-NN-"
233
0
            auto start = opt->second.currentValue.find('-') + 1;
234
0
            auto len = opt->second.currentValue.find('-', start) - start;
235
0
            if(start != String::npos)
236
0
                miscParams["monitorIndex"] = opt->second.currentValue.substr(start, len);
237
0
        }
238
239
#if OGRE_NO_QUAD_BUFFER_STEREO == 0
240
        if((opt = mOptions.find("Frame Sequential Stereo")) != end)
241
            miscParams["stereoMode"] = opt->second.currentValue;
242
#endif
243
0
        return ret;
244
0
    }
245
246
    //-----------------------------------------------------------------------
247
    void RenderSystem::_initRenderTargets(void)
248
0
    {
249
250
        // Init stats
251
0
        for (auto& rt : mRenderTargets)
252
0
        {
253
0
            rt.second->resetStatistics();
254
0
        }
255
0
    }
256
    //-----------------------------------------------------------------------
257
    void RenderSystem::_updateAllRenderTargets(bool swapBuffers)
258
0
    {
259
        // Update all in order of priority
260
        // This ensures render-to-texture targets get updated before render windows
261
0
        for (auto& rt : mPrioritisedRenderTargets)
262
0
        {
263
0
            if (rt.second->isActive() && rt.second->isAutoUpdated())
264
0
                rt.second->update(swapBuffers);
265
0
        }
266
0
    }
267
    //-----------------------------------------------------------------------
268
    void RenderSystem::_swapAllRenderTargetBuffers()
269
0
    {
270
0
        OgreProfile("_swapAllRenderTargetBuffers");
271
        // Update all in order of priority
272
        // This ensures render-to-texture targets get updated before render windows
273
0
        for (auto& rt : mPrioritisedRenderTargets)
274
0
        {
275
0
            if (rt.second->isActive() && rt.second->isAutoUpdated())
276
0
                rt.second->swapBuffers();
277
0
        }
278
0
    }
279
    //-----------------------------------------------------------------------
280
    void RenderSystem::_initialise()
281
0
    {
282
        // Have I been registered by call to Root::setRenderSystem?
283
        /** Don't do this anymore, just allow via Root
284
        RenderSystem* regPtr = Root::getSingleton().getRenderSystem();
285
        if (!regPtr || regPtr != this)
286
            // Register self - library user has come to me direct
287
            Root::getSingleton().setRenderSystem(this);
288
        */
289
290
291
        // Subclasses should take it from here
292
        // They should ALL call this superclass method from
293
        //   their own initialise() implementations.
294
        
295
0
        mProgramBound.fill(false);
296
0
    }
297
298
    //---------------------------------------------------------------------------------------------
299
    void RenderSystem::useCustomRenderSystemCapabilities(RenderSystemCapabilities* capabilities)
300
0
    {
301
0
        if (mRealCapabilities)
302
0
        {
303
0
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
304
0
                        "Custom render capabilities must be set before the RenderSystem is initialised");
305
0
        }
306
307
0
        if (capabilities->getRenderSystemName() != getName())
308
0
        {
309
0
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
310
0
                        "Trying to use RenderSystemCapabilities that were created for a different RenderSystem");
311
0
        }
312
313
0
        mCurrentCapabilities = capabilities;
314
0
        mUseCustomCapabilities = true;
315
0
    }
316
317
    //---------------------------------------------------------------------------------------------
318
    RenderWindow* RenderSystem::_createRenderWindow(const String& name, unsigned int width,
319
                                                    unsigned int height, bool fullScreen,
320
                                                    const NameValuePairList* miscParams)
321
0
    {
322
0
        if (mRenderTargets.find(name) != mRenderTargets.end())
323
0
        {
324
0
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Window with name '" + name + "' already exists");
325
0
        }
326
327
        // Log a message
328
0
        StringStream ss;
329
0
        ss << "RenderSystem::_createRenderWindow \"" << name << "\", " <<
330
0
            width << "x" << height << " ";
331
0
        if (fullScreen)
332
0
            ss << "fullscreen ";
333
0
        else
334
0
            ss << "windowed ";
335
336
0
        if (miscParams)
337
0
        {
338
0
            ss << " miscParams: ";
339
0
            NameValuePairList::const_iterator it;
340
0
            for (const auto& p : *miscParams)
341
0
            {
342
0
                ss << p.first << "=" << p.second << " ";
343
0
            }
344
0
        }
345
0
        LogManager::getSingleton().logMessage(ss.str());
346
347
0
        return NULL;
348
0
    }
349
    //---------------------------------------------------------------------------------------------
350
    void RenderSystem::destroyRenderWindow(const String& name)
351
0
    {
352
0
        destroyRenderTarget(name);
353
0
    }
354
    //---------------------------------------------------------------------------------------------
355
    void RenderSystem::destroyRenderTexture(const String& name)
356
0
    {
357
0
        destroyRenderTarget(name);
358
0
    }
359
    //---------------------------------------------------------------------------------------------
360
    void RenderSystem::destroyRenderTarget(const String& name)
361
0
    {
362
0
        RenderTarget* rt = detachRenderTarget(name);
363
0
        OGRE_DELETE rt;
364
0
    }
365
    //---------------------------------------------------------------------------------------------
366
    void RenderSystem::attachRenderTarget( RenderTarget &target )
367
0
    {
368
0
        assert( target.getPriority() < OGRE_NUM_RENDERTARGET_GROUPS );
369
370
0
        mRenderTargets.emplace(target.getName(), &target);
371
0
        mPrioritisedRenderTargets.emplace(target.getPriority(), &target);
372
0
    }
373
374
    //---------------------------------------------------------------------------------------------
375
    RenderTarget * RenderSystem::getRenderTarget( const String &name )
376
0
    {
377
0
        RenderTargetMap::iterator it = mRenderTargets.find( name );
378
0
        RenderTarget *ret = NULL;
379
380
0
        if( it != mRenderTargets.end() )
381
0
        {
382
0
            ret = it->second;
383
0
        }
384
385
0
        return ret;
386
0
    }
387
388
    //---------------------------------------------------------------------------------------------
389
    RenderTarget * RenderSystem::detachRenderTarget( const String &name )
390
0
    {
391
0
        RenderTargetMap::iterator it = mRenderTargets.find( name );
392
0
        RenderTarget *ret = NULL;
393
394
0
        if( it != mRenderTargets.end() )
395
0
        {
396
0
            ret = it->second;
397
            
398
            /* Remove the render target from the priority groups. */
399
0
            RenderTargetPriorityMap::iterator itarg, itargend;
400
0
            itargend = mPrioritisedRenderTargets.end();
401
0
            for( itarg = mPrioritisedRenderTargets.begin(); itarg != itargend; ++itarg )
402
0
            {
403
0
                if( itarg->second == ret ) {
404
0
                    mPrioritisedRenderTargets.erase( itarg );
405
0
                    break;
406
0
                }
407
0
            }
408
409
0
            mRenderTargets.erase( it );
410
0
        }
411
        /// If detached render target is the active render target, reset active render target
412
0
        if(ret == mActiveRenderTarget)
413
0
            mActiveRenderTarget = 0;
414
415
0
        return ret;
416
0
    }
417
    //-----------------------------------------------------------------------
418
    Viewport* RenderSystem::_getViewport(void)
419
0
    {
420
0
        return mActiveViewport;
421
0
    }
422
    //-----------------------------------------------------------------------
423
    void RenderSystem::_setTextureUnitSettings(size_t texUnit, TextureUnitState& tl)
424
0
    {
425
0
        if(texUnit >= getCapabilities()->getNumTextureUnits())
426
0
            return;
427
428
        // This method is only ever called to set a texture unit to valid details
429
        // The method _disableTextureUnit is called to turn a unit off
430
0
        TexturePtr tex = tl._getTexturePtr();
431
0
        if(!tex || tl.isTextureLoadFailing())
432
0
            tex = mTextureManager->_getWarningTexture();
433
434
0
        if(tl.getUnorderedAccessMipLevel() > -1)
435
0
        {
436
0
            tex->createShaderAccessPoint(texUnit, TA_READ_WRITE, tl.getUnorderedAccessMipLevel());
437
0
            return;
438
0
        }
439
440
        // Bind texture (may be blank)
441
0
        _setTexture(texUnit, true, tex);
442
443
0
        _setSampler(texUnit, *tl.getSampler());
444
445
0
        if(!getCapabilities()->hasCapability(RSC_FIXED_FUNCTION))
446
0
            return;
447
448
        // Set texture coordinate set
449
0
        _setTextureCoordSet(texUnit, tl.getTextureCoordSet());
450
451
        // Set blend modes
452
        // Note, colour before alpha is important
453
0
        _setTextureBlendMode(texUnit, tl.getColourBlendMode());
454
0
        _setTextureBlendMode(texUnit, tl.getAlphaBlendMode());
455
456
0
        auto calcMode = tl._deriveTexCoordCalcMethod();
457
0
        if(calcMode == TEXCALC_PROJECTIVE_TEXTURE)
458
0
        {
459
0
            _setTextureCoordCalculation(texUnit, calcMode, tl.getProjectiveTexturingFrustum());
460
0
        }
461
0
        else
462
0
        {
463
0
            _setTextureCoordCalculation(texUnit, calcMode);
464
0
        }
465
466
        // Change tetxure matrix 
467
0
        _setTextureMatrix(texUnit, tl.getTextureTransform());
468
0
    }
469
    //-----------------------------------------------------------------------
470
    void RenderSystem::_disableTextureUnit(size_t texUnit)
471
0
    {
472
0
        _setTexture(texUnit, false, sNullTexPtr);
473
0
    }
474
    //---------------------------------------------------------------------
475
    void RenderSystem::_disableTextureUnitsFrom(size_t texUnit)
476
0
    {
477
0
        size_t disableTo = OGRE_MAX_TEXTURE_LAYERS;
478
0
        if (disableTo > mDisabledTexUnitsFrom)
479
0
            disableTo = mDisabledTexUnitsFrom;
480
0
        mDisabledTexUnitsFrom = texUnit;
481
0
        for (size_t i = texUnit; i < disableTo; ++i)
482
0
        {
483
0
            _disableTextureUnit(i);
484
0
        }
485
0
    }
486
    //---------------------------------------------------------------------
487
    void RenderSystem::_cleanupDepthBuffers( bool bCleanManualBuffers )
488
0
    {
489
0
        for (auto& m : mDepthBufferPool)
490
0
        {
491
0
            for (auto *b : m.second)
492
0
            {
493
0
                if (bCleanManualBuffers || !b->isManual())
494
0
                    delete b;
495
0
            }
496
0
            m.second.clear();
497
0
        }
498
0
        mDepthBufferPool.clear();
499
0
    }
500
    //-----------------------------------------------------------------------
501
    void RenderSystem::_beginFrame(void)
502
0
    {
503
0
        if (!mActiveViewport)
504
0
            OGRE_EXCEPT(Exception::ERR_INVALID_STATE, "Cannot begin frame - no viewport selected.");
505
0
    }
506
    //-----------------------------------------------------------------------
507
    CullingMode RenderSystem::_getCullingMode(void) const
508
0
    {
509
0
        return mCullingMode;
510
0
    }
511
    //-----------------------------------------------------------------------
512
    void RenderSystem::setDepthBufferFor( RenderTarget *renderTarget )
513
0
    {
514
0
        uint16 poolNum = renderTarget->getDepthBufferPool();
515
0
        if( poolNum == RBP_NONE )
516
0
            return; //RenderTarget explicitly requested no depth buffer
517
518
0
        uint32 poolId = HashCombine(0, poolNum);
519
0
        poolId = HashCombine(poolId, renderTarget->getFSAA());
520
521
0
        if(!getCapabilities()->hasCapability(RSC_RTT_INDEPENDENT_BUFFER_SIZE))
522
0
        {
523
            //Depth buffer must be EXACT same size as RT
524
0
            poolId = HashCombine(poolId, renderTarget->getWidth());
525
0
            poolId = HashCombine(poolId, renderTarget->getHeight());
526
0
        }
527
528
        //Find a depth buffer in the pool
529
0
        bool bAttached = false;
530
0
        for (auto& d : mDepthBufferPool[poolId]) {
531
0
            bAttached = renderTarget->attachDepthBuffer(d);
532
0
            if (bAttached) break;
533
0
        }
534
535
        //Not found yet? Create a new one!
536
0
        if( !bAttached )
537
0
        {
538
0
            DepthBuffer *newDepthBuffer = _createDepthBufferFor( renderTarget );
539
540
0
            if( newDepthBuffer )
541
0
            {
542
0
                mDepthBufferPool[poolId].push_back( newDepthBuffer );
543
544
0
                bAttached = renderTarget->attachDepthBuffer( newDepthBuffer );
545
546
0
                OgreAssert( bAttached ,"A new DepthBuffer for a RenderTarget was created, but after creation"
547
0
                                     " it says it's incompatible with that RT" );
548
0
            }
549
0
            else
550
0
                LogManager::getSingleton().logWarning( "Couldn't create a suited DepthBuffer"
551
0
                                                       "for RT: " + renderTarget->getName());
552
0
        }
553
0
    }
554
    //-----------------------------------------------------------------------
555
    bool RenderSystem::isReverseDepthBufferEnabled() const
556
0
    {
557
0
        return mIsReverseDepthBufferEnabled;
558
0
    }
559
    //-----------------------------------------------------------------------
560
    void RenderSystem::reinitialise()
561
0
    {
562
0
        shutdown();
563
0
        _initialise();
564
0
    }
565
566
    void RenderSystem::shutdown(void)
567
0
    {
568
0
        for (auto& q : mHwOcclusionQueries)
569
0
        {
570
0
            OGRE_DELETE q;
571
0
        }
572
0
        mHwOcclusionQueries.clear();
573
574
0
        _cleanupDepthBuffers();
575
576
        // Remove all the render targets. Destroy primary target last since others may depend on it.
577
        // Keep mRenderTargets valid all the time, so that render targets could receive
578
        // appropriate notifications, for example FBO based about GL context destruction.
579
0
        RenderTarget* primary = 0;
580
0
        for (RenderTargetMap::iterator it = mRenderTargets.begin(); it != mRenderTargets.end(); /* note - no increment */)
581
0
        {
582
0
            RenderTarget* current = it->second;
583
0
            if (!primary && current->isPrimary())
584
0
            {
585
0
                ++it;
586
0
                primary = current;
587
0
            }
588
0
            else
589
0
            {
590
0
                it = mRenderTargets.erase(it);
591
0
                OGRE_DELETE current;
592
0
            }
593
0
        }
594
0
        OGRE_DELETE primary;
595
0
        mRenderTargets.clear();
596
597
0
        mPrioritisedRenderTargets.clear();
598
0
    }
599
600
    void RenderSystem::_setProjectionMatrix(Matrix4 m)
601
0
    {
602
0
        if (!mFixedFunctionParams) return;
603
604
0
        if (mActiveRenderTarget->requiresTextureFlipping())
605
0
        {
606
            // Invert transformed y
607
0
            m[1][0] = -m[1][0];
608
0
            m[1][1] = -m[1][1];
609
0
            m[1][2] = -m[1][2];
610
0
            m[1][3] = -m[1][3];
611
0
        }
612
613
0
        mFixedFunctionParams->setConstant(8, m);
614
0
        applyFixedFunctionParams(mFixedFunctionParams, GPV_GLOBAL);
615
0
    }
616
    //-----------------------------------------------------------------------
617
    void RenderSystem::_beginGeometryCount(void)
618
0
    {
619
0
        mBatchCount = mFaceCount = mVertexCount = 0;
620
0
    }
621
    //-----------------------------------------------------------------------
622
    void RenderSystem::_render(const RenderOperation& op)
623
0
    {
624
        // Update stats
625
0
        size_t val;
626
627
0
        if (op.useIndexes)
628
0
            val = op.indexData->indexCount;
629
0
        else
630
0
            val = op.vertexData->vertexCount;
631
632
0
        size_t trueInstanceNum = std::max<size_t>(op.numberOfInstances,1);
633
0
        val *= trueInstanceNum;
634
635
        // account for a pass having multiple iterations
636
0
        if (mCurrentPassIterationCount > 1)
637
0
            val *= mCurrentPassIterationCount;
638
0
        mCurrentPassIterationNum = 0;
639
640
0
        switch(op.operationType)
641
0
        {
642
0
        case RenderOperation::OT_TRIANGLE_LIST:
643
0
            mFaceCount += (val / 3);
644
0
            break;
645
0
        case RenderOperation::OT_TRIANGLE_LIST_ADJ:
646
0
            mFaceCount += (val / 6);
647
0
            break;
648
0
        case RenderOperation::OT_TRIANGLE_STRIP_ADJ:
649
0
            mFaceCount += (val / 2 - 2);
650
0
            break;
651
0
        case RenderOperation::OT_TRIANGLE_STRIP:
652
0
        case RenderOperation::OT_TRIANGLE_FAN:
653
0
            mFaceCount += (val - 2);
654
0
            break;
655
0
        default:
656
0
            break;
657
0
        }
658
659
0
        mVertexCount += op.vertexData->vertexCount * trueInstanceNum;
660
0
        mBatchCount += mCurrentPassIterationCount;
661
662
        // sort out clip planes
663
        // have to do it here in case of matrix issues
664
0
        if (mClipPlanesDirty)
665
0
        {
666
0
            setClipPlanesImpl(mClipPlanes);
667
0
            mClipPlanesDirty = false;
668
0
        }
669
0
    }
670
    //-----------------------------------------------------------------------
671
    void RenderSystem::setInvertVertexWinding(bool invert)
672
0
    {
673
0
        mInvertVertexWinding = invert;
674
0
    }
675
    //-----------------------------------------------------------------------
676
    bool RenderSystem::getInvertVertexWinding(void) const
677
0
    {
678
0
        return mInvertVertexWinding;
679
0
    }
680
    //---------------------------------------------------------------------
681
    void RenderSystem::setClipPlanes(const PlaneList& clipPlanes)
682
0
    {
683
0
        if (clipPlanes != mClipPlanes)
684
0
        {
685
0
            mClipPlanes = clipPlanes;
686
0
            mClipPlanesDirty = true;
687
0
        }
688
0
    }
689
    //-----------------------------------------------------------------------
690
    void RenderSystem::_notifyCameraRemoved(const Camera* cam)
691
0
    {
692
0
        for (auto& rt : mRenderTargets)
693
0
        {
694
0
            auto target = rt.second;
695
0
            target->_notifyCameraRemoved(cam);
696
0
        }
697
0
    }
698
699
    //---------------------------------------------------------------------
700
    bool RenderSystem::updatePassIterationRenderState(void)
701
0
    {
702
0
        if (mCurrentPassIterationCount <= 1)
703
0
            return false;
704
705
        // Update derived depth bias
706
0
        if (mDerivedDepthBias)
707
0
        {
708
0
            _setDepthBias(mDerivedDepthBiasBase + mDerivedDepthBiasMultiplier * mCurrentPassIterationNum,
709
0
                          mDerivedDepthBiasSlopeScale);
710
0
        }
711
712
0
        --mCurrentPassIterationCount;
713
0
        ++mCurrentPassIterationNum;
714
715
0
        const uint16 mask = GPV_PASS_ITERATION_NUMBER;
716
717
0
        for (int i = 0; i < GPT_COUNT; i++)
718
0
        {
719
0
            if (!mActiveParameters[i])
720
0
                continue;
721
0
            mActiveParameters[i]->incPassIterationNumber();
722
0
            bindGpuProgramParameters(GpuProgramType(i), mActiveParameters[i], mask);
723
0
        }
724
725
0
        return true;
726
0
    }
727
728
    //-----------------------------------------------------------------------
729
    void RenderSystem::setSharedListener(Listener* listener)
730
0
    {
731
0
        assert(msSharedEventListener == NULL || listener == NULL); // you can set or reset, but for safety not directly override
732
0
        msSharedEventListener = listener;
733
0
    }
734
    //-----------------------------------------------------------------------
735
    RenderSystem::Listener* RenderSystem::getSharedListener(void)
736
0
    {
737
0
        return msSharedEventListener;
738
0
    }
739
    //-----------------------------------------------------------------------
740
    void RenderSystem::addListener(Listener* l)
741
0
    {
742
0
        mEventListeners.push_back(l);
743
0
    }
744
    //-----------------------------------------------------------------------
745
    void RenderSystem::removeListener(Listener* l)
746
0
    {
747
0
        mEventListeners.remove(l);
748
0
    }
749
    //-----------------------------------------------------------------------
750
    void RenderSystem::fireEvent(const String& name, const NameValuePairList* params)
751
0
    {
752
0
        for(auto& el : mEventListeners)
753
0
        {
754
0
            el->eventOccurred(name, params);
755
0
        }
756
757
0
        if(msSharedEventListener)
758
0
            msSharedEventListener->eventOccurred(name, params);
759
0
    }
760
    //-----------------------------------------------------------------------
761
    void RenderSystem::destroyHardwareOcclusionQuery( HardwareOcclusionQuery *hq)
762
0
    {
763
0
        auto end = mHwOcclusionQueries.end();
764
0
        auto i = std::find(mHwOcclusionQueries.begin(), end, hq);
765
0
        if (i != end)
766
0
        {
767
0
            mHwOcclusionQueries.erase(i);
768
0
            OGRE_DELETE hq;
769
0
        }
770
0
    }
771
    //-----------------------------------------------------------------------
772
    void RenderSystem::bindGpuProgram(GpuProgram* prg)
773
0
    {
774
0
        auto gptype = prg->getType();
775
        // mark clip planes dirty if changed (programmable can change space)
776
0
        if(gptype == GPT_VERTEX_PROGRAM && !mClipPlanes.empty() && !mProgramBound[gptype])
777
0
            mClipPlanesDirty = true;
778
779
0
        mProgramBound[gptype] = true;
780
0
    }
781
    //-----------------------------------------------------------------------
782
    void RenderSystem::unbindGpuProgram(GpuProgramType gptype)
783
0
    {
784
        // mark clip planes dirty if changed (programmable can change space)
785
0
        if(gptype == GPT_VERTEX_PROGRAM && !mClipPlanes.empty() && mProgramBound[gptype])
786
0
            mClipPlanesDirty = true;
787
788
0
        mProgramBound[gptype] = false;
789
0
    }
790
    //-----------------------------------------------------------------------
791
    bool RenderSystem::isGpuProgramBound(GpuProgramType gptype)
792
0
    {
793
0
        return mProgramBound[gptype];
794
0
    }
795
    //---------------------------------------------------------------------
796
    void RenderSystem::_setTextureProjectionRelativeTo(bool enabled, const Vector3& pos)
797
0
    {
798
0
        mTexProjRelative = enabled;
799
0
        mTexProjRelativeOrigin = pos;
800
801
0
    }
802
    //---------------------------------------------------------------------
803
    const String& RenderSystem::_getDefaultViewportMaterialScheme( void ) const
804
0
    {
805
0
#ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
806
0
        if (!getCapabilities()->hasCapability(RSC_FIXED_FUNCTION))
807
0
        {
808
0
            return MSN_SHADERGEN;
809
0
        }
810
0
#endif
811
0
        return MSN_DEFAULT;
812
0
    }
813
    //---------------------------------------------------------------------
814
    void RenderSystem::setGlobalInstanceVertexBuffer(const HardwareVertexBufferSharedPtr& val)
815
0
    {
816
0
        OgreAssert(!val || val->isInstanceData(), "not an instance buffer");
817
0
        mSchemeInstancingData[_getDefaultViewportMaterialScheme()].vertexBuffer = val;
818
0
    }
819
    void RenderSystem::enableSchemeInstancing(const String& materialScheme, const HardwareVertexBufferPtr& buffer,
820
                                              VertexDeclaration* decl, uint32 instanceCount)
821
0
    {
822
0
        OgreAssert(!buffer || buffer->isInstanceData(), "not an instance buffer");
823
0
        OgreAssert(decl, "null vertex declaration");
824
0
        OgreAssert(instanceCount > 1, "instance count must be greater than 1");
825
0
        mSchemeInstancingData.emplace(materialScheme, GlobalInstancingData{buffer, decl, instanceCount});
826
0
    }
827
828
    //---------------------------------------------------------------------
829
    void RenderSystem::getCustomAttribute(const String& name, void* pData)
830
0
    {
831
0
        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Attribute not found.", "RenderSystem::getCustomAttribute");
832
0
    }
833
834
    void RenderSystem::initConfigOptions()
835
0
    {
836
        // FS setting possibilities
837
0
        ConfigOption optFullScreen;
838
0
        optFullScreen.name = "Full Screen";
839
0
        optFullScreen.possibleValues.push_back( "No" );
840
0
        optFullScreen.possibleValues.push_back( "Yes" );
841
0
        optFullScreen.currentValue = optFullScreen.possibleValues[0];
842
0
        optFullScreen.immutable = false;
843
0
        mOptions[optFullScreen.name] = optFullScreen;
844
845
        // Video mode possibilities, can be overwritten by actual values
846
0
        ConfigOption optVideoMode;
847
0
        optVideoMode.name = "Video Mode";
848
0
        optVideoMode.possibleValues.push_back("1920 x 1080");
849
0
        optVideoMode.possibleValues.push_back("1280 x 720");
850
0
        optVideoMode.possibleValues.push_back("800 x 600");
851
0
        optVideoMode.currentValue = optVideoMode.possibleValues.back();
852
0
        optVideoMode.immutable = false;
853
0
        mOptions[optVideoMode.name] = optVideoMode;
854
855
0
        ConfigOption optVSync;
856
0
        optVSync.name = "VSync";
857
0
        optVSync.immutable = false;
858
0
        optVSync.possibleValues.push_back("No");
859
0
        optVSync.possibleValues.push_back("Yes");
860
0
        optVSync.currentValue = optVSync.possibleValues[1];
861
0
        mOptions[optVSync.name] = optVSync;
862
863
0
        ConfigOption optVSyncInterval;
864
0
        optVSyncInterval.name = "VSync Interval";
865
0
        optVSyncInterval.immutable = false;
866
0
        optVSyncInterval.possibleValues.push_back("1");
867
0
        optVSyncInterval.possibleValues.push_back("2");
868
0
        optVSyncInterval.possibleValues.push_back("3");
869
0
        optVSyncInterval.possibleValues.push_back("4");
870
0
        optVSyncInterval.currentValue = optVSyncInterval.possibleValues[0];
871
0
        mOptions[optVSyncInterval.name] = optVSyncInterval;
872
873
0
        ConfigOption optSRGB;
874
0
        optSRGB.name = "sRGB Gamma Conversion";
875
0
        optSRGB.immutable = false;
876
0
        optSRGB.possibleValues.push_back("No");
877
0
        optSRGB.possibleValues.push_back("Yes");
878
0
        optSRGB.currentValue = optSRGB.possibleValues[0];
879
0
        mOptions[optSRGB.name] = optSRGB;
880
881
0
        ConfigOption optHDRDisplay;
882
0
        optHDRDisplay.name = "HDR Display";
883
0
        optHDRDisplay.immutable = false;
884
0
        optHDRDisplay.possibleValues.push_back("No");
885
0
        optHDRDisplay.possibleValues.push_back("Yes");
886
0
        optHDRDisplay.currentValue = optHDRDisplay.possibleValues[0];
887
0
        mOptions[optHDRDisplay.name] = optHDRDisplay;
888
889
#if OGRE_NO_QUAD_BUFFER_STEREO == 0
890
        ConfigOption optStereoMode;
891
        optStereoMode.name = "Frame Sequential Stereo";
892
        optStereoMode.possibleValues.push_back("Off");
893
        optStereoMode.possibleValues.push_back("On");
894
        optStereoMode.currentValue = optStereoMode.possibleValues[0];
895
        optStereoMode.immutable = false;
896
897
        mOptions[optStereoMode.name] = optStereoMode;
898
#endif
899
0
    }
900
901
    CompareFunction RenderSystem::reverseCompareFunction(CompareFunction func)
902
0
    {
903
0
        switch(func)
904
0
        {
905
0
        default:
906
0
            return func;
907
0
        case CMPF_LESS:
908
0
            return CMPF_GREATER;
909
0
        case CMPF_LESS_EQUAL:
910
0
            return CMPF_GREATER_EQUAL;
911
0
        case CMPF_GREATER_EQUAL:
912
0
            return CMPF_LESS_EQUAL;
913
0
        case CMPF_GREATER:
914
0
            return CMPF_LESS;
915
0
        }
916
0
    }
917
918
    bool RenderSystem::flipFrontFace() const
919
0
    {
920
0
        return mInvertVertexWinding != mActiveRenderTarget->requiresTextureFlipping();
921
0
    }
922
923
    void RenderSystem::setStencilCheckEnabled(bool enabled)
924
0
    {
925
0
        mStencilState.enabled = enabled;
926
0
        if (!enabled)
927
0
            setStencilState(mStencilState);
928
0
    }
929
    void RenderSystem::setStencilBufferParams(CompareFunction func, uint32 refValue, uint32 compareMask,
930
                                              uint32 writeMask, StencilOperation stencilFailOp,
931
                                              StencilOperation depthFailOp, StencilOperation passOp,
932
                                              bool twoSidedOperation)
933
0
    {
934
0
        mStencilState.compareOp = func;
935
0
        mStencilState.referenceValue = refValue;
936
0
        mStencilState.compareMask = compareMask;
937
0
        mStencilState.writeMask = writeMask;
938
0
        mStencilState.stencilFailOp = stencilFailOp;
939
0
        mStencilState.depthFailOp = depthFailOp;
940
0
        mStencilState.depthStencilPassOp = passOp;
941
0
        mStencilState.twoSidedOperation = twoSidedOperation;
942
0
        if(mStencilState.enabled)
943
0
            setStencilState(mStencilState);
944
0
    }
945
}
946