Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/forks/sandbox_light/src/external/ogremath/WIN32/OgreTimer.cpp @ 7908

Last change on this file since 7908 was 7908, checked in by rgrieder, 13 years ago

Stripped down trunk to form a new light sandbox.

  • Property svn:eol-style set to native
File size: 6.7 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "ogremath/OgreTimer.h"
30
31#include "ogremath/OgreBitwise.h"
32
33using namespace Ogre;
34
35//-------------------------------------------------------------------------
36Timer::Timer()
37        : mTimerMask( 0 )
38{
39        reset();
40}
41
42//-------------------------------------------------------------------------
43Timer::~Timer()
44{
45}
46
47//-------------------------------------------------------------------------
48bool Timer::setOption( const String & key, const void * val )
49{
50        if ( key == "QueryAffinityMask" )
51        {
52                // Telling timer what core to use for a timer read
53                DWORD newTimerMask = * static_cast < const DWORD * > ( val );
54
55                // Get the current process core mask
56                DWORD procMask;
57                DWORD sysMask;
58#if _MSC_VER >= 1400 && defined (_M_X64)
59                GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
60#else
61                GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
62#endif
63
64                // If new mask is 0, then set to default behavior, otherwise check
65                // to make sure new timer core mask overlaps with process core mask
66                // and that new timer core mask is a power of 2 (i.e. a single core)
67                if( ( newTimerMask == 0 ) ||
68                        ( ( ( newTimerMask & procMask ) != 0 ) && Bitwise::isPO2( newTimerMask ) ) )
69                {
70                        mTimerMask = newTimerMask;
71                        return true;
72                }
73        }
74
75        return false;
76}
77
78//-------------------------------------------------------------------------
79void Timer::reset()
80{
81    // Get the current process core mask
82        DWORD procMask;
83        DWORD sysMask;
84#if _MSC_VER >= 1400 && defined (_M_X64)
85        GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
86#else
87        GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
88#endif
89
90        // If procMask is 0, consider there is only one core available
91        // (using 0 as procMask will cause an infinite loop below)
92        if (procMask == 0)
93                procMask = 1;
94
95        // Find the lowest core that this process uses
96        if( mTimerMask == 0 )
97        {
98                mTimerMask = 1;
99                while( ( mTimerMask & procMask ) == 0 )
100                {
101                        mTimerMask <<= 1;
102                }
103        }
104
105        HANDLE thread = GetCurrentThread();
106
107        // Set affinity to the first core
108        DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
109
110        // Get the constant frequency
111        QueryPerformanceFrequency(&mFrequency);
112
113        // Query the timer
114        QueryPerformanceCounter(&mStartTime);
115        mStartTick = GetTickCount();
116
117        // Reset affinity
118        SetThreadAffinityMask(thread, oldMask);
119
120        mLastTime = 0;
121        mZeroClock = clock();
122}
123
124//-------------------------------------------------------------------------
125unsigned long Timer::getMilliseconds()
126{
127    LARGE_INTEGER curTime;
128
129        HANDLE thread = GetCurrentThread();
130
131        // Set affinity to the first core
132        DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
133
134        // Query the timer
135        QueryPerformanceCounter(&curTime);
136
137        // Reset affinity
138        SetThreadAffinityMask(thread, oldMask);
139
140    LONGLONG newTime = curTime.QuadPart - mStartTime.QuadPart;
141   
142    // scale by 1000 for milliseconds
143    unsigned long newTicks = (unsigned long) (1000 * newTime / mFrequency.QuadPart);
144
145    // detect and compensate for performance counter leaps
146    // (surprisingly common, see Microsoft KB: Q274323)
147    unsigned long check = GetTickCount() - mStartTick;
148    signed long msecOff = (signed long)(newTicks - check);
149    if (msecOff < -100 || msecOff > 100)
150    {
151        // We must keep the timer running forward :)
152        LONGLONG adjust = (std::min)(msecOff * mFrequency.QuadPart / 1000, newTime - mLastTime);
153        mStartTime.QuadPart += adjust;
154        newTime -= adjust;
155
156        // Re-calculate milliseconds
157        newTicks = (unsigned long) (1000 * newTime / mFrequency.QuadPart);
158    }
159
160    // Record last time for adjust
161    mLastTime = newTime;
162
163    return newTicks;
164}
165
166//-------------------------------------------------------------------------
167unsigned long Timer::getMicroseconds()
168{
169    LARGE_INTEGER curTime;
170
171        HANDLE thread = GetCurrentThread();
172
173        // Set affinity to the first core
174        DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);
175
176        // Query the timer
177        QueryPerformanceCounter(&curTime);
178
179        // Reset affinity
180        SetThreadAffinityMask(thread, oldMask);
181
182        LONGLONG newTime = curTime.QuadPart - mStartTime.QuadPart;
183   
184    // get milliseconds to check against GetTickCount
185    unsigned long newTicks = (unsigned long) (1000 * newTime / mFrequency.QuadPart);
186   
187    // detect and compensate for performance counter leaps
188    // (surprisingly common, see Microsoft KB: Q274323)
189    unsigned long check = GetTickCount() - mStartTick;
190    signed long msecOff = (signed long)(newTicks - check);
191    if (msecOff < -100 || msecOff > 100)
192    {
193        // We must keep the timer running forward :)
194        LONGLONG adjust = (std::min)(msecOff * mFrequency.QuadPart / 1000, newTime - mLastTime);
195        mStartTime.QuadPart += adjust;
196        newTime -= adjust;
197    }
198
199    // Record last time for adjust
200    mLastTime = newTime;
201
202    // scale by 1000000 for microseconds
203    unsigned long newMicro = (unsigned long) (1000000 * newTime / mFrequency.QuadPart);
204
205    return newMicro;
206}
207
208//-------------------------------------------------------------------------
209unsigned long Timer::getMillisecondsCPU()
210{
211        clock_t newClock = clock();
212        return (unsigned long)( (float)( newClock - mZeroClock ) / ( (float)CLOCKS_PER_SEC / 1000.0 ) ) ;
213}
214
215//-------------------------------------------------------------------------
216unsigned long Timer::getMicrosecondsCPU()
217{
218        clock_t newClock = clock();
219        return (unsigned long)( (float)( newClock - mZeroClock ) / ( (float)CLOCKS_PER_SEC / 1000000.0 ) ) ;
220}
Note: See TracBrowser for help on using the repository browser.