fixed incorrect checking of the existence of GLX_EXT_swap_control and friends
[demo_prior] / src / osd.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <drawtext.h>
5 #include "cgmath/cgmath.h"
6 #include "opengl.h"
7 #include "osd.h"
8 #include "demo.h"
9
10
11 struct message {
12         long start_time, show_until;
13         char *str;
14         cgm_vec3 color;
15         struct message *next;
16 };
17 static struct message *msglist;
18
19 struct text {
20         char *str;
21         cgm_vec2 pos;
22         cgm_vec3 color;
23         struct text *next;
24 };
25 static struct text *txlist;
26
27 static long timeout = 2000;
28 static long trans_time = 250;
29
30
31 void set_message_timeout(long tm)
32 {
33         timeout = tm;
34 }
35
36 void osd_printf(const char *fmt, ...)
37 {
38         va_list ap;
39         va_start(ap, fmt);
40         show_messagev(timeout, 1, 1, 1, fmt, ap);
41         va_end(ap);
42 }
43
44 void show_message(long timeout, float r, float g, float b, const char *fmt, ...)
45 {
46         va_list ap;
47         va_start(ap, fmt);
48         show_messagev(timeout, r, g, b, fmt, ap);
49         va_end(ap);
50 }
51
52 void show_messagev(long timeout, float r, float g, float b, const char *fmt, va_list ap)
53 {
54         char buf[512];
55         struct message *msg;
56         struct message dummy;
57         int len;
58
59         vsnprintf(buf, sizeof buf, fmt, ap);
60
61         if(!(msg = malloc(sizeof *msg))) {
62                 perror("failed to allocate memory");
63                 abort();
64         }
65         len = strlen(buf);
66         if(!(msg->str = malloc(len + 1))) {
67                 perror("failed to allocate memory");
68                 abort();
69         }
70         memcpy(msg->str, buf, len + 1);
71         msg->start_time = time_msec;
72         msg->show_until = time_msec + timeout;
73         msg->color.x = r;
74         msg->color.y = g;
75         msg->color.z = b;
76
77         dummy.next = msglist;
78         struct message *prev = &dummy;
79         while(prev->next && prev->next->show_until < msg->show_until) {
80                 prev = prev->next;
81         }
82         msg->next = prev->next;
83         prev->next = msg;
84         msglist = dummy.next;
85 }
86
87 void print_text(float x, float y, float r, float g, float b, const char *fmt, ...)
88 {
89         va_list ap;
90         va_start(ap, fmt);
91         print_textv(x, y, r, g, b, fmt, ap);
92         va_end(ap);
93 }
94
95 void print_textv(float x, float y, float r, float g, float b, const char *fmt, va_list ap)
96 {
97         char buf[512];
98         int len;
99         struct text *tx;
100
101         vsnprintf(buf, sizeof buf, fmt, ap);
102
103         if(!(tx = malloc(sizeof *tx))) {
104                 perror("failed to allocate memory");
105                 abort();
106         }
107         len = strlen(buf);
108         if(!(tx->str = malloc(len + 1))) {
109                 perror("failed to allocate memory");
110                 abort();
111         }
112         memcpy(tx->str, buf, len + 1);
113         tx->color.x = r;
114         tx->color.y = g;
115         tx->color.z = b;
116         tx->pos.x = x;
117         tx->pos.y = -y;
118
119         tx->next = txlist;
120         txlist = tx;
121 }
122
123 void draw_osd(void)
124 {
125         if(!fnt_ui) return;
126
127         while(msglist && msglist->show_until <= time_msec) {
128                 struct message *msg = msglist;
129                 msglist = msg->next;
130                 free(msg->str);
131                 free(msg);
132         }
133
134         dtx_use_font(fnt_ui, fnt_ui_size);
135
136         glMatrixMode(GL_PROJECTION);
137         glPushMatrix();
138         glLoadIdentity();
139         glOrtho(0, win_width, -win_height, 0, -1, 1);
140         glMatrixMode(GL_MODELVIEW);
141         glPushMatrix();
142         glLoadIdentity();
143
144         glPushAttrib(GL_ENABLE_BIT);
145         glDisable(GL_LIGHTING);
146         glDisable(GL_DEPTH_TEST);
147         glEnable(GL_BLEND);
148         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
149         glUseProgram(0);
150
151         struct message *msg = msglist;
152         while(msg) {
153                 long t = time_msec - msg->start_time;
154                 long dur = msg->show_until - msg->start_time;
155                 float alpha = cgm_smoothstep(0, trans_time, t) *
156                         (1.0 - cgm_smoothstep(dur - trans_time, dur, t));
157                 glColor4f(msg->color.x, msg->color.y, msg->color.z, alpha);
158                 glTranslatef(0, -dtx_line_height(), 0);
159                 dtx_string(msg->str);
160                 msg = msg->next;
161         }
162
163         while(txlist) {
164                 struct text *tx = txlist;
165                 txlist = txlist->next;
166
167                 glMatrixMode(GL_MODELVIEW);
168                 glLoadIdentity();
169                 glTranslatef(tx->pos.x, tx->pos.y, 0);
170
171                 glColor3f(tx->color.x, tx->color.y, tx->color.z);
172                 dtx_string(tx->str);
173
174                 free(tx->str);
175                 free(tx);
176         }
177
178         glPopAttrib();
179
180         glMatrixMode(GL_PROJECTION);
181         glPopMatrix();
182         glMatrixMode(GL_MODELVIEW);
183         glPopMatrix();
184 }