00001 //----------------------------------------------------------------------------------- 00002 // 00003 // Pro-Vocation Light Engine (PVLE) 00004 // Copyright (C) 2007-2009 Sukender, KinoX & Buzib 00005 // For more information, contact us : sukender@free.fr 00006 // 00007 // This program is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 3 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // For any use that is not compatible with the terms of the GNU 00013 // General Public License, please contact the authors for alternative 00014 // licensing options. 00015 // 00016 // This program is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 // GNU General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU General Public License along 00022 // with this program; if not, write to the Free Software Foundation, Inc., 00023 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 // 00025 //----------------------------------------------------------------------------------- 00026 00027 #include <PVLE/Util/FPSLimiter.h> 00028 #include <OpenThreads/Thread> 00029 #include <limits.h> 00030 #include <float.h> 00031 #include <algorithm> 00032 00033 const double MIN_SLEEP_DELAY = 0; // In microseconds 00034 //const double SECURITY_DELAY = 1000; // In microseconds 00035 00036 namespace Util { 00037 00038 FPSLimiter::FPSLimiter(UINT nbFrameTypes) : nbFrameTypes(nbFrameTypes) { 00039 ASSERT(nbFrameTypes>0); 00040 lastFrame = new double[nbFrameTypes]; 00041 minDelay = new double[nbFrameTypes]; 00042 std::fill(lastFrame, lastFrame+nbFrameTypes, -1); 00043 std::fill(minDelay , minDelay +nbFrameTypes, -1); 00044 } 00045 00046 00047 bool FPSLimiter::testFrameNeeded(double time, UINT type) { 00048 ASSERT(type < nbFrameTypes); 00049 //if (minDelay[type] <= 0) return true; // No limit => No sleep 00050 if (lastFrame[type] < 0) return true; // lastFrame[type] < 0 means uninitialized 00051 return time - lastFrame[type] >= minDelay[type]; 00052 } 00053 00054 00055 void FPSLimiter::operator()(double time) const { 00056 double cur_sleep_delay, sleep_delay = DBL_MAX; 00057 for(UINT type=0; type<nbFrameTypes; ++type) { 00058 if (minDelay[type] <= 0) return; // No limit => No sleep 00059 if (lastFrame[type] < 0) continue; // lastFrame[type] < 0 means uninitialized 00060 cur_sleep_delay = minDelay[type] - time + lastFrame[type]; // minDelay[type] - (time - lastFrame[type]) 00061 if (cur_sleep_delay < sleep_delay) sleep_delay = cur_sleep_delay; 00062 } 00063 if (sleep_delay == DBL_MAX || sleep_delay <= 0) return; 00064 00065 sleep_delay *= 1e6; // To put in microseconds 00066 00067 if (sleep_delay >= MIN_SLEEP_DELAY) OpenThreads::Thread::microSleep(static_cast<UINT>(sleep_delay)); 00068 //if (sleep_delay > SECURITY_DELAY) { 00069 // OpenThreads::Thread::microSleep(static_cast<UINT>(sleep_delay - SECURITY_DELAY)); 00070 // sleep_delay = SECURITY_DELAY; 00071 //} 00072 //OpenThreads::Thread::microSleep(static_cast<UINT>(sleep_delay / 5.)); 00073 } 00074 00075 } // namespace Util