Move timer functionality from util/ to common/

The main timer functionality (get absolute time) is moved to common/ for
use in ANGLE itself (in upcoming overlay change).  util/Timer.h is no
longer an abstract class and uses this functionality to implement the
timer.

Bug: angleproject:3757
Change-Id: I3fe418778d80d1089c9bfe43a9e8098e43236f18
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1769061
Reviewed-by: Cody Northrop <cnorthrop@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Tim Van Patten <timvp@google.com>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/samples/sample_util/SampleApplication.cpp b/samples/sample_util/SampleApplication.cpp
index 635ba6b..e27db78 100644
--- a/samples/sample_util/SampleApplication.cpp
+++ b/samples/sample_util/SampleApplication.cpp
@@ -68,7 +68,6 @@
         angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ApplicationDir));
 
     mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion);
-    mTimer.reset(CreateTimer());
     mOSWindow = OSWindow::New();
 }
 
@@ -158,12 +157,12 @@
         result   = -1;
     }
 
-    mTimer->start();
+    mTimer.start();
     double prevTime = 0.0;
 
     while (mRunning)
     {
-        double elapsedTime = mTimer->getElapsedTime();
+        double elapsedTime = mTimer.getElapsedTime();
         double deltaTime   = elapsedTime - prevTime;
 
         step(static_cast<float>(deltaTime), elapsedTime);
diff --git a/samples/sample_util/SampleApplication.h b/samples/sample_util/SampleApplication.h
index e6247c4..1b187a3 100644
--- a/samples/sample_util/SampleApplication.h
+++ b/samples/sample_util/SampleApplication.h
@@ -61,7 +61,7 @@
     uint32_t mHeight;
     bool mRunning;
 
-    std::unique_ptr<Timer> mTimer;
+    Timer mTimer;
     EGLWindow *mEGLWindow;
     OSWindow *mOSWindow;
 
diff --git a/samples/tex_redef_microbench/TexRedefMicroBench.cpp b/samples/tex_redef_microbench/TexRedefMicroBench.cpp
index cc3f2d8..fb8d8987 100644
--- a/samples/tex_redef_microbench/TexRedefMicroBench.cpp
+++ b/samples/tex_redef_microbench/TexRedefMicroBench.cpp
@@ -130,12 +130,6 @@
 
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
-        mOrigTimer         = CreateTimer();
-        mResizeDrawTimer   = CreateTimer();
-        mResizeDefineTimer = CreateTimer();
-        mNewTexDrawTimer   = CreateTimer();
-        mNewTexDefineTimer = CreateTimer();
-
         return true;
     }
 
@@ -191,54 +185,54 @@
         // unreleated to texture creation. mTimeFrame is set to true on the fifth frame.
         if (mTimeFrame)
         {
-            mOrigTimer->start();
+            mOrigTimer.start();
         }
 
         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
 
         if (mTimeFrame)
         {
-            mOrigTimer->stop();
+            mOrigTimer.stop();
             // This timer indicates draw time for an already-created texture resident on the GPU,
             // which needs no updates. It will be faster than the other draws.
-            std::cout << "Original texture draw: " << mOrigTimer->getElapsedTime() * 1000 << "msec"
+            std::cout << "Original texture draw: " << mOrigTimer.getElapsedTime() * 1000 << "msec"
                       << std::endl;
 
             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
             // Now, change the texture dimensions of the original texture
-            mResizeDefineTimer->start();
+            mResizeDefineTimer.start();
             defineSquareTexture2D(mTextureIds[0], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsResize);
-            mResizeDefineTimer->stop();
+            mResizeDefineTimer.stop();
 
-            mResizeDrawTimer->start();
+            mResizeDrawTimer.start();
             glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
-            mResizeDrawTimer->stop();
+            mResizeDrawTimer.stop();
             // This timer indicates draw time for a texture which has already been used in a draw,
             // causing the underlying resource to be allocated, and then resized, requiring resource
             // reallocation and related overhead.
             std::cout << "Resized texture definition: "
-                      << mResizeDefineTimer->getElapsedTime() * 1000 << "msec" << std::endl;
-            std::cout << "Resized texture draw: " << mResizeDrawTimer->getElapsedTime() * 1000
+                      << mResizeDefineTimer.getElapsedTime() * 1000 << "msec" << std::endl;
+            std::cout << "Resized texture draw: " << mResizeDrawTimer.getElapsedTime() * 1000
                       << "msec" << std::endl;
 
             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
             // Create texure at same dimensions we resized previous texture to
-            mNewTexDefineTimer->start();
+            mNewTexDefineTimer.start();
             defineSquareTexture2D(mTextureIds[1], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsNewTex);
-            mNewTexDefineTimer->stop();
+            mNewTexDefineTimer.stop();
 
-            mNewTexDrawTimer->start();
+            mNewTexDrawTimer.start();
             glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
-            mNewTexDrawTimer->stop();
+            mNewTexDrawTimer.stop();
             // This timer indicates draw time for a texture newly created this frame. The underlying
             // resource will need to be created, but because it has not previously been used, there
             // is no already-resident texture object to manage. This draw is expected to be faster
             // than the resized texture draw.
             std::cout << "Newly created texture definition: "
-                      << mNewTexDefineTimer->getElapsedTime() * 1000 << "msec" << std::endl;
-            std::cout << "Newly created texture draw: " << mNewTexDrawTimer->getElapsedTime() * 1000
+                      << mNewTexDefineTimer.getElapsedTime() * 1000 << "msec" << std::endl;
+            std::cout << "Newly created texture draw: " << mNewTexDrawTimer.getElapsedTime() * 1000
                       << "msec" << std::endl;
         }
 
@@ -269,11 +263,11 @@
     GLubyte *mPixelsResize;
     GLubyte *mPixelsNewTex;
 
-    Timer *mOrigTimer;
-    Timer *mResizeDrawTimer;
-    Timer *mResizeDefineTimer;
-    Timer *mNewTexDrawTimer;
-    Timer *mNewTexDefineTimer;
+    Timer mOrigTimer;
+    Timer mResizeDrawTimer;
+    Timer mResizeDefineTimer;
+    Timer mNewTexDrawTimer;
+    Timer mNewTexDefineTimer;
     bool mTimeFrame;
     unsigned int mFrameCount;
 };
diff --git a/samples/tri_fan_microbench/TriFanMicroBench.cpp b/samples/tri_fan_microbench/TriFanMicroBench.cpp
index 658c994..b86624a 100644
--- a/samples/tri_fan_microbench/TriFanMicroBench.cpp
+++ b/samples/tri_fan_microbench/TriFanMicroBench.cpp
@@ -157,8 +157,6 @@
 
         createVertexBuffers();
 
-        mFanTimer     = CreateTimer();
-        mTriTimer     = CreateTimer();
         mFanTotalTime = 0;
         mTriTotalTime = 0;
 
@@ -191,33 +189,33 @@
         glEnableVertexAttribArray(0);
 
         // Draw using triangle fans, stored in VBO
-        mFanTimer->start();
+        mFanTimer.start();
         for (unsigned i = 0; i < mNumSquares; ++i)
         {
             glBindBuffer(GL_ARRAY_BUFFER, mFanBufId[i]);
             glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
             glDrawArrays(GL_TRIANGLE_FAN, 0, mNumFanVerts);
         }
-        mFanTimer->stop();
+        mFanTimer.stop();
 
         mFanTotalTime += static_cast<unsigned int>(
-            mFanTimer->getElapsedTime() * 1000);  // convert from usec to msec when accumulating
+            mFanTimer.getElapsedTime() * 1000);  // convert from usec to msec when accumulating
 
         // Clear to eliminate driver-side gains from occlusion
         glClear(GL_COLOR_BUFFER_BIT);
 
         // Draw using triangles, stored in VBO
-        mTriTimer->start();
+        mTriTimer.start();
         for (unsigned i = 1; i < mNumSquares; ++i)
         {
             glBindBuffer(GL_ARRAY_BUFFER, mTriBufId[i]);
             glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
             glDrawArrays(GL_TRIANGLES, 0, mNumTriVerts);
         }
-        mTriTimer->stop();
+        mTriTimer.stop();
 
         mTriTotalTime += static_cast<unsigned int>(
-            mTriTimer->getElapsedTime() * 1000);  // convert from usec to msec when accumulating
+            mTriTimer.getElapsedTime() * 1000);  // convert from usec to msec when accumulating
 
         mFrameCount++;
     }
@@ -230,8 +228,8 @@
     GLuint mFanBufId[mNumSquares];
     GLuint mTriBufId[mNumSquares];
 
-    Timer *mFanTimer;
-    Timer *mTriTimer;
+    Timer mFanTimer;
+    Timer mTriTimer;
     unsigned int mFrameCount;
     unsigned int mTriTotalTime;
     unsigned int mFanTotalTime;
diff --git a/src/common/system_utils.h b/src/common/system_utils.h
index 0fa3ff8..1191fac 100644
--- a/src/common/system_utils.h
+++ b/src/common/system_utils.h
@@ -26,6 +26,9 @@
 bool PrependPathToEnvironmentVar(const char *variableName, const char *path);
 bool IsDirectory(const char *filename);
 
+// Get absolute time in seconds.  Use this function to get an absolute time with an unknown origin.
+double GetCurrentTime();
+
 // Run an application and get the output.  Gets a nullptr-terminated set of args to execute the
 // application with, and returns the stdout and stderr outputs as well as the exit code.
 //
diff --git a/src/common/system_utils_linux.cpp b/src/common/system_utils_linux.cpp
index 26a1fd1..04d323c 100644
--- a/src/common/system_utils_linux.cpp
+++ b/src/common/system_utils_linux.cpp
@@ -44,4 +44,12 @@
 {
     return "so";
 }
+
+double GetCurrentTime()
+{
+    struct timespec currentTime;
+    clock_gettime(CLOCK_MONOTONIC, &currentTime);
+    return currentTime.tv_sec + currentTime.tv_nsec * 1e-9;
+}
+
 }  // namespace angle
diff --git a/src/common/system_utils_mac.cpp b/src/common/system_utils_mac.cpp
index b41827b..88939fa 100644
--- a/src/common/system_utils_mac.cpp
+++ b/src/common/system_utils_mac.cpp
@@ -10,7 +10,10 @@
 
 #include <unistd.h>
 
+#include <CoreServices/CoreServices.h>
 #include <mach-o/dyld.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
 #include <cstdlib>
 #include <vector>
 
@@ -49,4 +52,13 @@
 {
     return "dylib";
 }
+
+double GetCurrentTime()
+{
+    mach_timebase_info_data_t timebaseInfo;
+    mach_timebase_info(&timebaseInfo);
+
+    double secondCoeff = timebaseInfo.numer * 1e-9 / timebaseInfo.denom;
+    return secondCoeff * mach_absolute_time();
+}
 }  // namespace angle
diff --git a/src/common/system_utils_win.cpp b/src/common/system_utils_win.cpp
index 47d41aa..6aa196c 100644
--- a/src/common/system_utils_win.cpp
+++ b/src/common/system_utils_win.cpp
@@ -131,6 +131,17 @@
     return ";";
 }
 
+double GetCurrentTime()
+{
+    LARGE_INTEGER frequency = {};
+    QueryPerformanceFrequency(&frequency);
+
+    LARGE_INTEGER curTime;
+    QueryPerformanceCounter(&curTime);
+
+    return static_cast<double>(curTime.QuadPart) / frequency.QuadPart;
+}
+
 bool RunApp(const std::vector<const char *> &args,
             std::string *stdoutOut,
             std::string *stderrOut,
diff --git a/src/tests/egl_tests/EGLSurfaceTest.cpp b/src/tests/egl_tests/EGLSurfaceTest.cpp
index 5a796bf..f95c054 100644
--- a/src/tests/egl_tests/EGLSurfaceTest.cpp
+++ b/src/tests/egl_tests/EGLSurfaceTest.cpp
@@ -376,28 +376,28 @@
     {
         if (maxInterval >= 1)
         {
-            std::unique_ptr<Timer> timer(CreateTimer());
+            Timer timer;
 
             eglSwapInterval(mDisplay, 1);
-            timer->start();
+            timer.start();
             for (int i = 0; i < 180; ++i)
             {
                 eglSwapBuffers(mDisplay, mWindowSurface);
             }
-            timer->stop();
+            timer.stop();
             ASSERT_EGL_SUCCESS();
 
             // 120 frames at 60fps should take 3s.  At lower fps, it should take even longer.  At
             // 144fps, it would take 1.25s.  Let's use 1s as a lower bound.
-            ASSERT_GT(timer->getElapsedTime(), 1);
+            ASSERT_GT(timer.getElapsedTime(), 1);
         }
 
         if (minInterval <= 0)
         {
-            std::unique_ptr<Timer> timer(CreateTimer());
+            Timer timer;
 
             eglSwapInterval(mDisplay, 0);
-            timer->start();
+            timer.start();
             for (int i = 0; i < 100; ++i)
             {
                 eglSwapBuffers(mDisplay, mWindowSurface);
@@ -406,7 +406,7 @@
                 // http://anglebug.com/3144.
                 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
             }
-            timer->stop();
+            timer.stop();
             ASSERT_EGL_SUCCESS();
 
             // 100 no-op swaps should be fairly fast, though there is no guarantee how fast it can
@@ -415,7 +415,7 @@
             // TODO(syoussefi): if a surface doesn't truly allow no-vsync, this can fail.  Until
             // there's a way to query the exact minInterval from the surface, this test cannot be
             // enabled.
-            // ASSERT_LT(timer->getElapsedTime(), 1);
+            // ASSERT_LT(timer.getElapsedTime(), 1);
         }
     }
 }
diff --git a/src/tests/perf_tests/ANGLEPerfTest.cpp b/src/tests/perf_tests/ANGLEPerfTest.cpp
index 889071c..0668c64 100644
--- a/src/tests/perf_tests/ANGLEPerfTest.cpp
+++ b/src/tests/perf_tests/ANGLEPerfTest.cpp
@@ -113,11 +113,10 @@
 
 double MonotonicallyIncreasingTime(angle::PlatformMethods *platform)
 {
-    ANGLERenderTest *renderTest = static_cast<ANGLERenderTest *>(platform->context);
     // Move the time origin to the first call to this function, to avoid generating unnecessarily
     // large timestamps.
-    static double origin = renderTest->getTimer()->getAbsoluteTime();
-    return renderTest->getTimer()->getAbsoluteTime() - origin;
+    static double origin = angle::GetCurrentTime();
+    return angle::GetCurrentTime() - origin;
 }
 
 void DumpTraceEventsToJSONFile(const std::vector<TraceEvent> &traceEvents,
@@ -165,7 +164,6 @@
     : mName(name),
       mBackend(backend),
       mStory(story),
-      mTimer(CreateTimer()),
       mGPUTimeNs(0),
       mSkipTest(false),
       mStepsToRun(std::numeric_limits<unsigned int>::max()),
@@ -189,7 +187,6 @@
 
 ANGLEPerfTest::~ANGLEPerfTest()
 {
-    SafeDelete(mTimer);
 }
 
 void ANGLEPerfTest::run()
@@ -205,7 +202,7 @@
         doRunLoop(kCalibrationRunTimeSeconds);
 
         // Scale steps down according to the time that exeeded one second.
-        double scale = kCalibrationRunTimeSeconds / mTimer->getElapsedTime();
+        double scale = kCalibrationRunTimeSeconds / mTimer.getElapsedTime();
         mStepsToRun  = static_cast<size_t>(static_cast<double>(mNumStepsPerformed) * scale);
 
         // Calibration allows the perf test runner script to save some time.
@@ -235,7 +232,7 @@
 {
     mNumStepsPerformed = 0;
     mRunning           = true;
-    mTimer->start();
+    mTimer.start();
     startTest();
 
     while (mRunning)
@@ -244,7 +241,7 @@
         if (mRunning)
         {
             ++mNumStepsPerformed;
-            if (mTimer->getElapsedTime() > maxRunTime)
+            if (mTimer.getElapsedTime() > maxRunTime)
             {
                 mRunning = false;
             }
@@ -255,7 +252,7 @@
         }
     }
     finishTest();
-    mTimer->stop();
+    mTimer.stop();
 }
 
 void ANGLEPerfTest::SetUp() {}
@@ -265,7 +262,7 @@
 double ANGLEPerfTest::printResults()
 {
     double elapsedTimeSeconds[2] = {
-        mTimer->getElapsedTime(),
+        mTimer.getElapsedTime(),
         mGPUTimeNs * 1e-9,
     };
 
diff --git a/src/tests/perf_tests/ANGLEPerfTest.h b/src/tests/perf_tests/ANGLEPerfTest.h
index d016249..ace529d 100644
--- a/src/tests/perf_tests/ANGLEPerfTest.h
+++ b/src/tests/perf_tests/ANGLEPerfTest.h
@@ -69,8 +69,6 @@
     // Called right before timer is stopped to let the test wait for asynchronous operations.
     virtual void finishTest() {}
 
-    Timer *getTimer() const { return mTimer; }
-
   protected:
     void run();
     void SetUp() override;
@@ -88,7 +86,7 @@
     std::string mName;
     std::string mBackend;
     std::string mStory;
-    Timer *mTimer;
+    Timer mTimer;
     uint64_t mGPUTimeNs;
     bool mSkipTest;
     std::unique_ptr<perf_test::PerfResultReporter> mReporter;
diff --git a/src/tests/perf_tests/EGLInitializePerf.cpp b/src/tests/perf_tests/EGLInitializePerf.cpp
index c068a88..c8b4421 100644
--- a/src/tests/perf_tests/EGLInitializePerf.cpp
+++ b/src/tests/perf_tests/EGLInitializePerf.cpp
@@ -20,7 +20,7 @@
 // Only applies to D3D11
 struct Captures final : private angle::NonCopyable
 {
-    Timer *timer           = CreateTimer();
+    Timer timer;
     size_t loadDLLsMS      = 0;
     size_t createDeviceMS  = 0;
     size_t initResourcesMS = 0;
@@ -29,7 +29,7 @@
 double CapturePlatform_currentTime(angle::PlatformMethods *platformMethods)
 {
     Captures *captures = static_cast<Captures *>(platformMethods->context);
-    return captures->timer->getElapsedTime();
+    return captures->timer.getElapsedTime();
 }
 
 void CapturePlatform_histogramCustomCounts(angle::PlatformMethods *platformMethods,
diff --git a/src/tests/perf_tests/InstancingPerf.cpp b/src/tests/perf_tests/InstancingPerf.cpp
index b06e4cf..be160de 100644
--- a/src/tests/perf_tests/InstancingPerf.cpp
+++ b/src/tests/perf_tests/InstancingPerf.cpp
@@ -276,7 +276,7 @@
     // Animatino makes the test more interesting visually, but also eats up many CPU cycles.
     if (params.animationEnabled)
     {
-        float time = static_cast<float>(mTimer->getElapsedTime());
+        float time = static_cast<float>(mTimer.getElapsedTime());
 
         for (size_t pointIndex = 0; pointIndex < mTranslateData.size(); ++pointIndex)
         {
diff --git a/util/Timer.cpp b/util/Timer.cpp
new file mode 100644
index 0000000..691e392
--- /dev/null
+++ b/util/Timer.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Timer.cpp: Implementation of a high precision timer class.
+//
+
+#include "util/Timer.h"
+
+#include "common/system_utils.h"
+
+Timer::Timer() : mRunning(false), mStartTime(0), mStopTime(0) {}
+
+void Timer::start()
+{
+    mStartTime = angle::GetCurrentTime();
+    mRunning   = true;
+}
+
+void Timer::stop()
+{
+    mStopTime = angle::GetCurrentTime();
+    mRunning  = false;
+}
+
+double Timer::getElapsedTime() const
+{
+    double endTime;
+    if (mRunning)
+    {
+        endTime = angle::GetCurrentTime();
+    }
+    else
+    {
+        endTime = mStopTime;
+    }
+
+    return endTime - mStartTime;
+}
diff --git a/util/Timer.h b/util/Timer.h
index f1c1b3e..143be28 100644
--- a/util/Timer.h
+++ b/util/Timer.h
@@ -1,5 +1,5 @@
 //
-// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -9,23 +9,23 @@
 
 #include "util/util_export.h"
 
-class ANGLE_UTIL_EXPORT Timer
+class ANGLE_UTIL_EXPORT Timer final
 {
   public:
-    virtual ~Timer() {}
+    Timer();
+    ~Timer() {}
 
-    // Timer functionality: Use start() and stop() to record the duration and use getElapsedTime()
-    // to query that duration.  If getElapsedTime() is called in between, it will report the elapsed
-    // time since start().
-    virtual void start()                  = 0;
-    virtual void stop()                   = 0;
-    virtual double getElapsedTime() const = 0;
+    // Use start() and stop() to record the duration and use getElapsedTime() to query that
+    // duration.  If getElapsedTime() is called in between, it will report the elapsed time since
+    // start().
+    void start();
+    void stop();
+    double getElapsedTime() const;
 
-    // Timestamp functionality: Use getAbsoluteTime() to get an absolute time with an unknown
-    // origin. This time moves forward regardless of start()/stop().
-    virtual double getAbsoluteTime() = 0;
+  private:
+    bool mRunning;
+    double mStartTime;
+    double mStopTime;
 };
 
-ANGLE_UTIL_EXPORT Timer *CreateTimer();
-
 #endif  // SAMPLE_UTIL_TIMER_H
diff --git a/util/osx/OSXTimer.cpp b/util/osx/OSXTimer.cpp
deleted file mode 100644
index c202080..0000000
--- a/util/osx/OSXTimer.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// OSXTimer.cpp: Implementation of a high precision timer class on OSX
-
-#include "util/osx/OSXTimer.h"
-
-#include <CoreServices/CoreServices.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-
-OSXTimer::OSXTimer() : mRunning(false), mSecondCoeff(0) {}
-
-double OSXTimer::getSecondCoeff()
-{
-    // If this is the first time we've run, get the timebase.
-    if (mSecondCoeff == 0.0)
-    {
-        mach_timebase_info_data_t timebaseInfo;
-        mach_timebase_info(&timebaseInfo);
-
-        mSecondCoeff = timebaseInfo.numer * (1.0 / 1000000000) / timebaseInfo.denom;
-    }
-
-    return mSecondCoeff;
-}
-
-void OSXTimer::start()
-{
-    mStartTime = mach_absolute_time();
-    // Cache secondCoeff
-    getSecondCoeff();
-    mRunning = true;
-}
-
-void OSXTimer::stop()
-{
-    mStopTime = mach_absolute_time();
-    mRunning  = false;
-}
-
-double OSXTimer::getElapsedTime() const
-{
-    if (mRunning)
-    {
-        return mSecondCoeff * (mach_absolute_time() - mStartTime);
-    }
-    else
-    {
-        return mSecondCoeff * (mStopTime - mStartTime);
-    }
-}
-
-double OSXTimer::getAbsoluteTime()
-{
-    return getSecondCoeff() * mach_absolute_time();
-}
-
-Timer *CreateTimer()
-{
-    return new OSXTimer();
-}
diff --git a/util/osx/OSXTimer.h b/util/osx/OSXTimer.h
deleted file mode 100644
index de7a9da..0000000
--- a/util/osx/OSXTimer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// OSXTimer.h: Definition of a high precision timer class on OSX
-
-#ifndef UTIL_OSX_TIMER_H_
-#define UTIL_OSX_TIMER_H_
-
-#include <stdint.h>
-#include <time.h>
-
-#include "util/Timer.h"
-
-class ANGLE_UTIL_EXPORT OSXTimer : public Timer
-{
-  public:
-    OSXTimer();
-
-    void start() override;
-    void stop() override;
-    double getElapsedTime() const override;
-
-    double getAbsoluteTime() override;
-
-  private:
-    double getSecondCoeff();
-
-    bool mRunning;
-    uint64_t mStartTime;
-    uint64_t mStopTime;
-    double mSecondCoeff;
-};
-
-#endif  // UTIL_OSX_TIMER_H_
diff --git a/util/posix/PosixTimer.cpp b/util/posix/PosixTimer.cpp
deleted file mode 100644
index 53cfd4f..0000000
--- a/util/posix/PosixTimer.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// PosixTimer.cpp: Implementation of a high precision timer class on POSIX
-
-#include "util/posix/PosixTimer.h"
-#include <iostream>
-
-PosixTimer::PosixTimer() : mRunning(false) {}
-
-namespace
-{
-uint64_t getCurrentTimeNs()
-{
-    struct timespec currentTime;
-    clock_gettime(CLOCK_MONOTONIC, &currentTime);
-    return currentTime.tv_sec * 1'000'000'000llu + currentTime.tv_nsec;
-}
-}  // anonymous namespace
-
-void PosixTimer::start()
-{
-    mStartTimeNs = getCurrentTimeNs();
-    mRunning     = true;
-}
-
-void PosixTimer::stop()
-{
-    mStopTimeNs = getCurrentTimeNs();
-    mRunning    = false;
-}
-
-double PosixTimer::getElapsedTime() const
-{
-    uint64_t endTimeNs;
-    if (mRunning)
-    {
-        endTimeNs = getCurrentTimeNs();
-    }
-    else
-    {
-        endTimeNs = mStopTimeNs;
-    }
-
-    return (endTimeNs - mStartTimeNs) * 1e-9;
-}
-
-double PosixTimer::getAbsoluteTime()
-{
-    return getCurrentTimeNs() * 1e-9;
-}
-
-Timer *CreateTimer()
-{
-    return new PosixTimer();
-}
diff --git a/util/posix/PosixTimer.h b/util/posix/PosixTimer.h
deleted file mode 100644
index 168639d..0000000
--- a/util/posix/PosixTimer.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// PosixTimer.h: Definition of a high precision timer class on Linux
-
-#ifndef UTIL_POSIX_TIMER_H
-#define UTIL_POSIX_TIMER_H
-
-#include <stdint.h>
-#include <time.h>
-
-#include "util/Timer.h"
-
-class ANGLE_UTIL_EXPORT PosixTimer : public Timer
-{
-  public:
-    PosixTimer();
-
-    void start() override;
-    void stop() override;
-    double getElapsedTime() const override;
-
-    double getAbsoluteTime() override;
-
-  private:
-    bool mRunning;
-    uint64_t mStartTimeNs;
-    uint64_t mStopTimeNs;
-};
-
-#endif  // UTIL_POSIX_TIMER_H
diff --git a/util/util.gni b/util/util.gni
index 9103948..492c875 100644
--- a/util/util.gni
+++ b/util/util.gni
@@ -24,6 +24,7 @@
   "util/OSWindow.cpp",
   "util/OSWindow.h",
   "util/Timer.h",
+  "util/Timer.cpp",
 ]
 
 util_win_sources = [
@@ -33,16 +34,12 @@
   "util/windows/win32/Win32Window.cpp",
   "util/windows/win32/Win32Window.h",
   "util/windows/Windows_system_utils.cpp",
-  "util/windows/WindowsTimer.cpp",
-  "util/windows/WindowsTimer.h",
   "util/windows/WGLWindow.h",
 ]
 
 util_win_shared_sources = [ "util/windows/WGLWindow.cpp" ]
 
 util_posix_sources = [
-  "util/posix/PosixTimer.cpp",
-  "util/posix/PosixTimer.h",
   "util/posix/Posix_crash_handler.cpp",
   "util/posix/Posix_system_utils.cpp",
 ]
@@ -68,8 +65,6 @@
 ]
 
 util_osx_sources = [
-  "util/osx/OSXTimer.cpp",
-  "util/osx/OSXTimer.h",
   "util/osx/OSXPixmap.mm",
   "util/osx/OSXPixmap.h",
   "util/osx/OSXWindow.mm",
diff --git a/util/windows/WindowsTimer.cpp b/util/windows/WindowsTimer.cpp
deleted file mode 100644
index 00d8abc..0000000
--- a/util/windows/WindowsTimer.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// Copyright 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// WindowsTimer.cpp: Implementation of a high precision timer class on Windows
-
-#include "util/windows/WindowsTimer.h"
-
-WindowsTimer::WindowsTimer() : mRunning(false), mStartTime(0), mStopTime(0), mFrequency(0) {}
-
-LONGLONG WindowsTimer::getFrequency()
-{
-    if (mFrequency == 0)
-    {
-        LARGE_INTEGER frequency = {};
-        QueryPerformanceFrequency(&frequency);
-
-        mFrequency = frequency.QuadPart;
-    }
-
-    return mFrequency;
-}
-
-void WindowsTimer::start()
-{
-    LARGE_INTEGER curTime;
-    QueryPerformanceCounter(&curTime);
-    mStartTime = curTime.QuadPart;
-
-    // Cache the frequency
-    getFrequency();
-
-    mRunning = true;
-}
-
-void WindowsTimer::stop()
-{
-    LARGE_INTEGER curTime;
-    QueryPerformanceCounter(&curTime);
-    mStopTime = curTime.QuadPart;
-
-    mRunning = false;
-}
-
-double WindowsTimer::getElapsedTime() const
-{
-    LONGLONG endTime;
-    if (mRunning)
-    {
-        LARGE_INTEGER curTime;
-        QueryPerformanceCounter(&curTime);
-        endTime = curTime.QuadPart;
-    }
-    else
-    {
-        endTime = mStopTime;
-    }
-
-    return static_cast<double>(endTime - mStartTime) / mFrequency;
-}
-
-double WindowsTimer::getAbsoluteTime()
-{
-    LARGE_INTEGER curTime;
-    QueryPerformanceCounter(&curTime);
-
-    return static_cast<double>(curTime.QuadPart) / getFrequency();
-}
-
-Timer *CreateTimer()
-{
-    return new WindowsTimer();
-}
diff --git a/util/windows/WindowsTimer.h b/util/windows/WindowsTimer.h
deleted file mode 100644
index 4358875..0000000
--- a/util/windows/WindowsTimer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// WindowsTimer.h: Definition of a high precision timer class on Windows
-
-#ifndef UTIL_WINDOWS_TIMER_H
-#define UTIL_WINDOWS_TIMER_H
-
-#include <windows.h>
-
-#include "util/Timer.h"
-
-class ANGLE_UTIL_EXPORT WindowsTimer : public Timer
-{
-  public:
-    WindowsTimer();
-
-    void start() override;
-    void stop() override;
-    double getElapsedTime() const override;
-
-    double getAbsoluteTime() override;
-
-  private:
-    LONGLONG getFrequency();
-
-    bool mRunning;
-    LONGLONG mStartTime;
-    LONGLONG mStopTime;
-    LONGLONG mFrequency;
-};
-
-#endif  // UTIL_WINDOWS_TIMER_H
diff --git a/util/windows/win32/Win32Window.cpp b/util/windows/win32/Win32Window.cpp
index 13f5e59..c422915 100644
--- a/util/windows/win32/Win32Window.cpp
+++ b/util/windows/win32/Win32Window.cpp
@@ -486,7 +486,6 @@
 
 Win32Window::Win32Window()
     : mIsVisible(false),
-      mSetVisibleTimer(CreateTimer()),
       mIsMouseInWindow(false),
       mNativeWindow(0),
       mParentWindow(0),
@@ -496,7 +495,6 @@
 Win32Window::~Win32Window()
 {
     destroy();
-    delete mSetVisibleTimer;
 }
 
 bool Win32Window::initialize(const std::string &name, int width, int height)
@@ -611,7 +609,7 @@
     // for a while before issuing screenshot if window was just made visible.
     {
         static const double WAIT_WINDOW_VISIBLE_MS = 0.5;  // Half a second for the animation
-        double timeSinceVisible                    = mSetVisibleTimer->getElapsedTime();
+        double timeSinceVisible                    = mSetVisibleTimer.getElapsedTime();
 
         if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS)
         {
@@ -804,8 +802,8 @@
 
     if (isVisible)
     {
-        mSetVisibleTimer->stop();
-        mSetVisibleTimer->start();
+        mSetVisibleTimer.stop();
+        mSetVisibleTimer.start();
     }
 }
 
diff --git a/util/windows/win32/Win32Window.h b/util/windows/win32/Win32Window.h
index 4f7c11f..a5c90d9 100644
--- a/util/windows/win32/Win32Window.h
+++ b/util/windows/win32/Win32Window.h
@@ -48,7 +48,7 @@
     std::string mChildClassName;
 
     bool mIsVisible;
-    Timer *mSetVisibleTimer;
+    Timer mSetVisibleTimer;
 
     bool mIsMouseInWindow;
 
diff --git a/util/x11/X11Window.cpp b/util/x11/X11Window.cpp
index c101916..66d555b 100644
--- a/util/x11/X11Window.cpp
+++ b/util/x11/X11Window.cpp
@@ -427,20 +427,18 @@
     XResizeWindow(mDisplay, mWindow, width, height);
     XFlush(mDisplay);
 
-    Timer *timer = CreateTimer();
-    timer->start();
+    Timer timer;
+    timer.start();
 
     // Wait until the window as actually been resized so that the code calling resize
     // can assume the window has been resized.
     const double kResizeWaitDelay = 0.2;
-    while ((mHeight != height || mWidth != width) && timer->getElapsedTime() < kResizeWaitDelay)
+    while ((mHeight != height || mWidth != width) && timer.getElapsedTime() < kResizeWaitDelay)
     {
         messageLoop();
         angle::Sleep(10);
     }
 
-    delete timer;
-
     return true;
 }