source: libcaca/trunk/caca/graphics.c @ 4094

Last change on this file since 4094 was 4094, checked in by Sam Hocevar, 10 years ago

Gather profiling information in caca_refresh_display() and caca_get_event().

  • Property svn:keywords set to Id
File size: 7.8 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id: graphics.c 4094 2009-12-06 21:21:40Z sam $
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  This file contains character and string drawing functions.
17 */
18
19#include "config.h"
20
21#if !defined(__KERNEL__)
22#   include <stdio.h>
23#   include <stdlib.h>
24#   include <string.h>
25#endif
26
27#include "caca.h"
28#include "caca_internals.h"
29
30/** \brief Set the display title.
31 *
32 *  If libcaca runs in a window, try to change its title. This works with
33 *  the ncurses, S-Lang, OpenGL, X11 and Win32 drivers.
34 *
35 *  If an error occurs, -1 is returned and \b errno is set accordingly:
36 *  - \c ENOSYS Display driver does not support setting the window title.
37 *
38 *  \param dp The libcaca display context.
39 *  \param title The desired display title.
40 *  \return 0 upon success, -1 if an error occurred.
41 */
42int caca_set_display_title(caca_display_t *dp, char const *title)
43{
44    int ret = dp->drv.set_display_title(dp, title);
45
46    if(ret)
47        seterrno(ENOSYS);
48
49    return ret;
50}
51
52/** \brief Get the display width.
53 *
54 *  If libcaca runs in a window, get the usable window width. This value can
55 *  be used for aspect ratio calculation. If libcaca does not run in a window
56 *  or if there is no way to know the font size, most drivers will assume a
57 *  6x10 font is being used. Note that the units are not necessarily pixels.
58 *
59 *  This function never fails.
60 *
61 *  \param dp The libcaca display context.
62 *  \return The display width.
63 */
64int caca_get_display_width(caca_display_t const *dp)
65{
66    return dp->drv.get_display_width(dp);
67}
68
69/** \brief Get the display height.
70 *
71 *  If libcaca runs in a window, get the usable window height. This value can
72 *  be used for aspect ratio calculation. If libcaca does not run in a window
73 *  or if there is no way to know the font size, assume a 6x10 font is being
74 *  used. Note that the units are not necessarily pixels.
75 *
76 *  This function never fails.
77 *
78 *  \param dp The libcaca display context.
79 *  \return The display height.
80 */
81int caca_get_display_height(caca_display_t const *dp)
82{
83    return dp->drv.get_display_height(dp);
84}
85
86/** \brief Set the refresh delay.
87 *
88 *  Set the refresh delay in microseconds. The refresh delay is used by
89 *  caca_refresh_display() to achieve constant framerate. See the
90 *  caca_refresh_display() documentation for more details.
91 *
92 *  If the argument is zero, constant framerate is disabled. This is the
93 *  default behaviour.
94 *
95 *  If an error occurs, -1 is returned and \b errno is set accordingly:
96 *  - \c EINVAL Refresh delay value is invalid.
97 *
98 *  \param dp The libcaca display context.
99 *  \param usec The refresh delay in microseconds.
100 *  \return 0 upon success, -1 if an error occurred.
101 */
102int caca_set_display_time(caca_display_t *dp, int usec)
103{
104    if(usec < 0)
105    {
106        seterrno(EINVAL);
107        return -1;
108    }
109
110    dp->delay = usec;
111    return 0;
112}
113
114/** \brief Get the display's average rendering time.
115 *
116 *  Get the average rendering time, which is the average measured time
117 *  between two caca_refresh_display() calls, in microseconds. If constant
118 *  framerate was activated by calling caca_set_display_time(), the average
119 *  rendering time will be close to the requested delay even if the real
120 *  rendering time was shorter.
121 *
122 *  This function never fails.
123 *
124 *  \param dp The libcaca display context.
125 *  \return The render time in microseconds.
126 */
127int caca_get_display_time(caca_display_t const *dp)
128{
129    return dp->rendertime;
130}
131
132/** \brief Flush pending changes and redraw the screen.
133 *
134 *  Flush all graphical operations and print them to the display device.
135 *  Nothing will show on the screen until this function is called.
136 *
137 *  If caca_set_display_time() was called with a non-zero value,
138 *  caca_refresh_display() will use that value to achieve constant
139 *  framerate: if two consecutive calls to caca_refresh_display() are within
140 *  a time range shorter than the value set with caca_set_display_time(),
141 *  the second call will be delayed before performing the screen refresh.
142 *
143 *  This function never fails.
144 *
145 *  \param dp The libcaca display context.
146 *  \return This function always returns 0.
147 */
148int caca_refresh_display(caca_display_t *dp)
149{
150#if defined PROF
151    caca_timer_t proftimer = { 0, 0 };
152#endif
153#if !defined(_DOXYGEN_SKIP_ME)
154#   define IDLE_USEC 5000
155#endif
156    int ticks = dp->lastticks + _caca_getticks(&dp->timer);
157
158#if defined PROF
159    _caca_getticks(&proftimer);
160#endif
161    dp->drv.display(dp);
162#if defined PROF
163    STAT_IADD(&dp->display_stat, _caca_getticks(&proftimer));
164#endif
165
166    /* Invalidate the dirty rectangle */
167    caca_clear_dirty_rect_list(dp->cv);
168
169    /* Once the display is finished, we can ack resizes */
170    if(dp->resize.resized)
171    {
172        dp->resize.resized = 0;
173        _caca_handle_resize(dp);
174    }
175
176#if defined PROF
177    _caca_getticks(&proftimer);
178#endif
179    /* Wait until dp->delay + time of last call */
180    ticks += _caca_getticks(&dp->timer);
181    for(ticks += _caca_getticks(&dp->timer);
182        ticks + IDLE_USEC < (int)dp->delay;
183        ticks += _caca_getticks(&dp->timer))
184    {
185        _caca_sleep(IDLE_USEC);
186    }
187#if defined PROF
188    STAT_IADD(&dp->wait_stat, _caca_getticks(&proftimer));
189#endif
190
191    /* Update the render time */
192    dp->rendertime = ticks;
193
194    dp->lastticks = ticks - dp->delay;
195
196    /* If we drifted too much, it's bad, bad, bad. */
197    if(dp->lastticks > (int)dp->delay)
198        dp->lastticks = 0;
199
200#if defined PROF
201    _caca_dump_stats();
202#endif
203
204    return 0;
205}
206
207/** \brief Show or hide the cursor.
208 *
209 *  Show or hide the cursor, for devices that support such a feature.
210 *
211 *  If an error occurs, -1 is returned and \b errno is set accordingly:
212 *  - \c ENOSYS Display driver does not support showing the cursor.
213 *
214 *  \param dp The libcaca display context.
215 *  \param flag 0 hides the cursor, 1 shows the system's default cursor
216 *              (usually a white rectangle). Other values are reserved for
217 *              future use.
218 *  \return 0 upon success, -1 if an error occurred.
219 */
220int caca_set_cursor(caca_display_t *dp, int flag)
221{
222    if(!dp->drv.set_cursor)
223    {
224        seterrno(ENOSYS);
225        return -1;
226    }
227
228    dp->drv.set_cursor(dp, flag);
229    return 0;
230}
231
232/** \brief Show or hide the mouse pointer.
233 *
234 *  Show or hide the mouse pointer. This function works with the ncurses,
235 *  S-Lang and X11 drivers.
236 *
237 *  If an error occurs, -1 is returned and \b errno is set accordingly:
238 *  - \c ENOSYS Display driver does not support hiding the mouse pointer.
239 *
240 *  \param dp The libcaca display context.
241 *  \param flag 0 hides the pointer, 1 shows the system's default pointer
242 *              (usually an arrow). Other values are reserved for future use.
243 *  \return 0 upon success, -1 if an error occurred.
244 */
245int caca_set_mouse(caca_display_t *dp, int flag)
246{
247    if(!dp->drv.set_mouse)
248    {
249        seterrno(ENOSYS);
250        return -1;
251    }
252
253    dp->drv.set_mouse(dp, flag);
254    return 0;
255}
256
257/*
258 * XXX: following functions are local
259 */
260
261void _caca_handle_resize(caca_display_t *dp)
262{
263    dp->drv.handle_resize(dp);
264
265    /* Tell libcaca we changed size */
266    if(dp->resize.w != caca_get_canvas_width(dp->cv)
267        || dp->resize.h != caca_get_canvas_height(dp->cv))
268    {
269        dp->resize.allow = 1;
270        caca_set_canvas_size(dp->cv, dp->resize.w, dp->resize.h);
271        dp->resize.allow = 0;
272    }
273}
274
275void _caca_set_term_title(char const *str)
276{
277#if defined(HAVE_GETENV)
278    char *term;
279
280    term = getenv("TERM");
281
282    if(!term || !strcmp(term, "linux"))
283        return;
284#endif
285
286    fprintf(stdout, "\033]0;%s\007", str);
287    fflush(stdout);
288}
289
Note: See TracBrowser for help on using the repository browser.