1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <sys/time.h>
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Timer helper for fps.  Returns seconds elapsed since first call to
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// getseconds(), as a double.
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static inline double getseconds() {
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static int first_call = 1;
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static struct timeval start_tv;
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static int start_tv_retv;
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const double usec_to_sec = 0.000001;
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (first_call) {
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    first_call = 0;
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    start_tv_retv = gettimeofday(&start_tv, NULL);
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  struct timeval tv;
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if ((0 == start_tv_retv) && (0 == gettimeofday(&tv, NULL)))
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return (tv.tv_sec - start_tv.tv_sec) + tv.tv_usec * usec_to_sec;
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 0.0;
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct FpsState {
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  double last_time;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int frame_count;
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/**
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Initialize the FpsState object.
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)inline void FpsInit(struct FpsState* state) {
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->last_time = getseconds();
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->frame_count = 0;
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/**
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Call this whenever you render, after calling FpsInit above.
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Returns 1 if the value should be displayed. In this case, the result will
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * be written to the |out_fps| parameter.
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)inline int FpsStep(struct FpsState* state, double* out_fps) {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const double kFpsUpdateSecs = 1.0f;
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  double current_time = getseconds();
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->frame_count++;
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (current_time < state->last_time + kFpsUpdateSecs)
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return 0;
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *out_fps = state->frame_count / (current_time - state->last_time);
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->last_time = current_time;
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  state->frame_count = 0;
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 1;
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
59