Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Drawing to the screen uses too much CPU

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Drawing to the screen uses too much CPU
Tobias Dammers
Member #2,604
August 2002
avatar

Why are you using the unreliable and unpredictable (in terms of accuracy) multithread-timing facilities at all? Here's what I usually do:
- I use a high-resolution timer like QueryPerformanceCounter (Linux has gettimeofday() which is supposed to be as exact; since I'm on a windows box, I haven't investigated this to any extent though). Wrote a nice wrapper (once, for all my future projects) around the various interfaces, falling back on allegro timers if all else fails.
- In my main loop, I first read the timer delta and accumulate it. I decide independently if I need to update logic (if (timer) > 0 for variable-delta, while (timer >= timeslice) for fixed-delta) and graphics (cap to, say, 60 Hz or whatever you like, or don't cap and just update only if logic has changed). After that, I sleep (with a user option to turn this off).
Works beautifully.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

BAF
Member #2,981
December 2002
avatar

Would you mind posting your framework?

Tobias Dammers
Member #2,604
August 2002
avatar

I might release a little library soon. In the meantime, here's my timer api.
(timer.h)

#ifndef TIMER_H
#define TIMER_H

void init_timer(bool use_qpc = false);
void stop_timer();
void start_timer(int timer_ms);
float get_timer_delta();
const char* get_timing_method_string();
float get_timer_accuracy();

#endif

(timer.cpp)

1#include <allegro.h>
2#ifdef ALLEGRO_WINDOWS
3 #include <winalleg.h>
4#endif
5#include "timer.h"
6 
7bool initialized = false;
8 
9int timer = 0;
10int timer_ms = 0;
11 
12#ifdef ALLEGRO_WINDOWS
13LARGE_INTEGER last_perf_count_li;
14LARGE_INTEGER perf_count_li;
15LARGE_INTEGER perf_freq_li;
16unsigned long long last_perf_count;
17unsigned long long perf_count;
18unsigned long long perf_freq;
19 
20unsigned long long li_to_ll(LARGE_INTEGER li) {
21 unsigned long long ll = li.HighPart;
22 ll = ll << 32;
23 ll |= li.LowPart;
24 return ll;
25}
26#endif
27 
28bool qpc_mode = false;
29 
30void timer_proc() {
31 ++timer;
32}
33END_OF_FUNCTION(timer_proc);
34 
35void init_timer(bool use_qpc) {
36#ifdef ALLEGRO_WINDOWS
37 if (use_qpc)
38 qpc_mode = QueryPerformanceFrequency(&perf_freq_li);
39 else
40#endif
41 qpc_mode = false;
42
43 if (qpc_mode)
44 perf_freq = li_to_ll(perf_freq_li);
45
46 if (!qpc_mode) {
47 LOCK_VARIABLE(timer);
48 LOCK_FUNCTION(timer_proc);
49 install_timer();
50 }
51
52 initialized = true;
53}
54 
55void stop_timer() {
56 if (!qpc_mode)
57 remove_int(timer_proc);
58}
59 
60void start_timer(int _timer_ms) {
61 if (qpc_mode) {
62#ifdef ALLEGRO_WINDOWS
63 QueryPerformanceCounter(&last_perf_count_li);
64 last_perf_count = li_to_ll(last_perf_count_li);
65#endif
66 }
67 else {
68 stop_timer();
69 timer_ms = _timer_ms;
70 install_int(timer_proc, timer_ms);
71 }
72}
73 
74float get_timer_delta() {
75 if (qpc_mode) {
76#ifdef ALLEGRO_WINDOWS
77 QueryPerformanceCounter(&perf_count_li);
78 perf_count = li_to_ll(perf_count_li);
79 float result = (float)((double)(perf_count - last_perf_count) / (double)perf_freq);
80 last_perf_count = perf_count;
81 return result;
82#else
83 return NULL;
84#endif
85 }
86 else {
87 float result = (float)timer * (float)timer_ms * 0.001f;
88 timer = 0;
89 return result;
90 }
91}
92 
93const char* get_timing_method_string() {
94 if (!initialized)
95 return "Not initialized!";
96 if (qpc_mode)
97#ifdef ALLEGRO_WINDOWS
98 return "QueryPerformanceCounter";
99#else
100 return "Something's terribly wrong";
101#endif
102 return "Allegro timer routines";
103}
104 
105float get_timer_accuracy() {
106 if (qpc_mode)
107#ifdef ALLEGRO_WINDOWS
108 return (float)perf_freq;
109#else
110 return 0.0f;
111#endif
112 if (timer_ms)
113 return 1000.0f / (float)timer_ms;
114 return 0.0f;
115}

And here's what the main loop does:
(snip from scene.cpp)

1bool SCENE::run() {
2 bool looping = true;
3 float dt = 0.0f;
4 float paintt = 0.0f;
5 float min_paintt = 0.5f;
6 fps = 0.0f;
7 logic_frametime = 0.0f;
8 render_frametime = 0.0f;
9 logic_frames = 0;
10 display_info = false;
11
12 get_timer_delta();
13
14 while (looping) {
15 while (keypressed()) {
16 switch (readkey() >> 8) {
17// removed irrelevant code here
18 case KEY_ESC:
19 looping = false;
20 break;
21 }
22 }
23
24 dt = get_timer_delta();
25 ++logic_frames;
26 tick(dt);
27
28 paint();
29
30 paintt += dt;
31
32 if (paintt > min_paintt) {
33 fps = (float)logic_frames / paintt;
34 logic_frames = 0;
35 paintt = 0.0f;
36 render_frametime = 1.0f / fps;
37 logic_frametime = render_frametime;
38 }
39
40 if (level_completed)
41 looping = false;
42 rest(1);
43 }
44 return level_completed;
45}

Makes sense?

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

 1   2 


Go to: