mirror of
https://github.com/edubart/otclient.git
synced 2025-12-14 12:49:47 +01:00
graphics optimization feature inspirated by diablo3 engine
* the rendering now consits of two panes - the background pane (for animated stuff like the map) - the foreground pane (for steady stuff, like UI) each pane has it own max FPS and works idependently this may increase graphics performance on many platforms
This commit is contained in:
113
src/framework/core/adaptativeframecounter.cpp
Normal file
113
src/framework/core/adaptativeframecounter.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "adaptativeframecounter.h"
|
||||
|
||||
AdaptativeFrameCounter::AdaptativeFrameCounter()
|
||||
{
|
||||
m_frames = 0;
|
||||
m_partialFrames = 0;
|
||||
m_partialFps = 0;
|
||||
m_maxPartialFps = 0;
|
||||
m_frameDelaySum = 0;
|
||||
m_mediumFrameDelay = 0;
|
||||
m_lastFps = 0;
|
||||
m_lastFrame = 0;
|
||||
m_maxFps = 0;
|
||||
m_sleepMicros = 0;
|
||||
m_mediumFrameDelay = 0;
|
||||
m_lastFpsUpdate = stdext::micros();
|
||||
m_lastPartialFpsUpdate = stdext::micros();
|
||||
}
|
||||
|
||||
bool AdaptativeFrameCounter::shouldProcessNextFrame()
|
||||
{
|
||||
if(m_maxFps == 0)
|
||||
return true;
|
||||
|
||||
ticks_t now = stdext::micros();
|
||||
if(now - m_lastFrame < m_bestFrameDelay)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AdaptativeFrameCounter::processNextFrame()
|
||||
{
|
||||
ticks_t now = stdext::micros();
|
||||
m_frames++;
|
||||
m_partialFrames++;
|
||||
m_frameDelaySum += now - m_lastFrame;
|
||||
m_lastFrame = now ;
|
||||
}
|
||||
|
||||
void AdaptativeFrameCounter::update()
|
||||
{
|
||||
ticks_t now = stdext::micros();
|
||||
ticks_t delta = now - m_lastPartialFpsUpdate;
|
||||
if(delta > 41000 && m_partialFrames > 0) {
|
||||
m_partialFps = m_partialFrames / (delta / 1000000.0f);
|
||||
m_lastPartialFpsUpdate = now;
|
||||
m_partialFrames = 0;
|
||||
}
|
||||
|
||||
delta = now - m_lastFpsUpdate;
|
||||
if(delta >= 1000000) {
|
||||
m_lastFps = m_frames;
|
||||
if(m_frames > 0)
|
||||
m_mediumFrameDelay = m_frameDelaySum / m_frames;
|
||||
else
|
||||
m_mediumFrameDelay = 0;
|
||||
m_lastFpsUpdate = now;
|
||||
m_frames = 0;
|
||||
m_frameDelaySum = 0;
|
||||
|
||||
//dump << stdext::format("FPS => %d Partial FPS => %d Frame Delay Hit => %.2f%%", m_lastFps, (int)m_partialFps, getFrameDelayHit());
|
||||
}
|
||||
}
|
||||
|
||||
void AdaptativeFrameCounter::setMaxFps(int maxFps)
|
||||
{
|
||||
maxFps = std::max(std::min(maxFps, 1000), 0);
|
||||
|
||||
if(maxFps != 0) {
|
||||
m_bestFrameDelay = 1000000 / maxFps;
|
||||
} else {
|
||||
m_maxPartialFps = 0;
|
||||
m_bestFrameDelay = 0;
|
||||
}
|
||||
m_maxFps = maxFps;
|
||||
}
|
||||
|
||||
int AdaptativeFrameCounter::getMaximumSleepMicros()
|
||||
{
|
||||
if(m_maxFps == 0)
|
||||
return 0;
|
||||
return m_lastFrame + m_bestFrameDelay - stdext::micros();
|
||||
}
|
||||
|
||||
float AdaptativeFrameCounter::getFrameDelayHit()
|
||||
{
|
||||
if(m_bestFrameDelay > 0)
|
||||
return ((m_bestFrameDelay - std::abs(m_bestFrameDelay - m_mediumFrameDelay)) * 100.0f) / (float)m_bestFrameDelay;
|
||||
else
|
||||
return 100.0f;
|
||||
}
|
||||
74
src/framework/core/adaptativeframecounter.h
Normal file
74
src/framework/core/adaptativeframecounter.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ADAPTATIVEFRAMECOUNTER_H
|
||||
#define ADAPTATIVEFRAMECOUNTER_H
|
||||
|
||||
#include <framework/global.h>
|
||||
|
||||
/**
|
||||
* Class that help counting and limiting frames per second in a application,
|
||||
* to make fps limit work as desired, this class requires 2 platforms prerequisites:
|
||||
* - the platform must have timer with a precision of at least 1ms
|
||||
* - the platform sleep must have a precision of at least 4ms
|
||||
*/
|
||||
class AdaptativeFrameCounter
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
// 4ms because most platforms has kernel timer of 250Hz
|
||||
MINIMUM_MICROS_SLEEP = 4000
|
||||
};
|
||||
|
||||
AdaptativeFrameCounter();
|
||||
|
||||
bool shouldProcessNextFrame();
|
||||
void processNextFrame();
|
||||
void update();
|
||||
void setMaxFps(int maxFps);
|
||||
bool isFpsLimitActive() { return m_maxFps != 0; }
|
||||
|
||||
int getMaximumSleepMicros();
|
||||
float getFrameDelayHit();
|
||||
int getLastFps() { return m_lastFps; }
|
||||
int getPartialFps() { return (int)m_partialFps; }
|
||||
int getMaxFps() { return m_maxFps; }
|
||||
float getMediumFrameDelay() { return m_mediumFrameDelay; }
|
||||
|
||||
private:
|
||||
int m_frames;
|
||||
int m_partialFrames;
|
||||
ticks_t m_partialFpsDelta;
|
||||
float m_partialFps;
|
||||
float m_maxPartialFps;
|
||||
ticks_t m_frameDelaySum;
|
||||
ticks_t m_mediumFrameDelay;
|
||||
ticks_t m_lastFrame;
|
||||
int m_lastFps;
|
||||
int m_maxFps;
|
||||
ticks_t m_bestFrameDelay;
|
||||
ticks_t m_lastFpsUpdate;
|
||||
ticks_t m_lastPartialFpsUpdate;
|
||||
float m_sleepMicros;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
ticks_t asyncTicks();
|
||||
ticks_t ticks() { return m_currentTicks; }
|
||||
ticks_t ticksElapsed(long prevTicks) { return m_currentTicks - prevTicks; }
|
||||
ticks_t ticksElapsed(ticks_t prevTicks) { return m_currentTicks - prevTicks; }
|
||||
ticks_t ticksFor(int delay) { return m_currentTicks + delay; }
|
||||
|
||||
float asyncTime() { return asyncTicks()/1000.0f; }
|
||||
|
||||
Reference in New Issue
Block a user