This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via b287df058124c3d9039a8bfe5475927a1d5fc68e (commit) via def91911864e39790b6a69b674b65c7b59c6933c (commit) via 4576af9cfc5ff38fb8b5cd804d0f05eb891b83f6 (commit) via 2b7cd8c924e4a9b4b0a946d9f5b22067789cf18c (commit) via b26b80ae54cda6dc76f1b002e221ae62dd5989de (commit) via 32a00d3651aa79bc3db01c0f2ce4e1c89c6e3c97 (commit) via cf00485b00ae80031789a382a764e21cd70ec706 (commit) via ec6f972853a8eec5ccea7df42077ab6745938ccc (commit) via d9a8b27f7b932cc340d5d0251ab292fe388216a7 (commit) from 1f9af7dcef377ae227faa484f8f7183583bfefe4 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/b287df058124c3d9039a8bfe5475927a1d5fc...
commit b287df058124c3d9039a8bfe5475927a1d5fc68e Author: Cyril Hrubis metan@ucw.cz Date: Mon Jun 24 19:53:41 2013 +0200
doc: backends: Add GP_BackendAddTimer() docs.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/doc/backends.txt b/doc/backends.txt index ff8cffb..151e654 100644 --- a/doc/backends.txt +++ b/doc/backends.txt @@ -412,6 +412,25 @@ queue and the call returns. } -------------------------------------------------------------------------------
+GP_BackendAddTimer +^^^^^^^^^^^^^^^^^^ + +[source,c] +------------------------------------------------------------------------------- +#include <backends/GP_Backend.h> +/* or */ +#include <GP.h> + +void GP_BackendAddTimer(GP_Backend *self, GP_Timer *timer); +------------------------------------------------------------------------------- + +Adds a link:input.html#Timers[timer] to the backend timer queue. + +Timers added to the backend are processed automatically while you call any of +backend 'Poll' or 'Wait' functions. + +If timer callback is set to 'NULL' a timer event is pushed to the backend +input queue once timer has expired otherwise timer callback is called.
GP_BackendEventsQueued ^^^^^^^^^^^^^^^^^^^^^^
http://repo.or.cz/w/gfxprim.git/commit/def91911864e39790b6a69b674b65c7b59c69...
commit def91911864e39790b6a69b674b65c7b59c6933c Author: Cyril Hrubis metan@ucw.cz Date: Mon Jun 24 19:41:51 2013 +0200
doc: input: Add GP_Timer and GP_TimeStamp docs.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/doc/input.txt b/doc/input.txt index a98428e..5db6158 100644 --- a/doc/input.txt +++ b/doc/input.txt @@ -5,7 +5,7 @@ are stored in the link:event_queue.html[event queue].
Possibly in contrast with other libraries there is not always 1:1 correspondence between input driver and backend graphics driver. That means -that you can, for example, use linux input events together with X Window +that you can, for example, use Linux input events together with X Window without any problems. You can even write application that doesn't draw any graphics at all and still use some of the input drivers. There are, of course, cases where input driver is created only together with graphics driver, this @@ -40,7 +40,7 @@ typedef struct GP_Event { struct timeval time;
/* - * Cursor position, possition on screen accumulated + * Cursor position, position on screen accumulated * from all pointer devices */ uint32_t cursor_x; @@ -64,17 +64,19 @@ enum GP_EventType { GP_EV_REL, /* relative event */ GP_EV_ABS, /* absolute event */ GP_EV_SYS, /* system events window close, resize... */ - GP_EV_MAX = GP_EV_SYS, /* maximum, greater values are free */ + GP_EV_TMR, /* timer expired event */ + GP_EV_MAX = GP_EV_TMR, /* maximum, greater values are free */ }; -------------------------------------------------------------------------------
-The event 'type' determines highlevel nature of the event. +The event 'type' determines high-level nature of the event.
* Key events covers keyboard button presses, mouse buttons, etc. * Relative events covers mouse coordinates, mouse wheel, etc. * Absolute events covers touchscreens and tablets * System events are used for propagating window close and window resize events +* Timer expired event are generated by when a link:#Timers[timer] has expired. * Values greater than 'GP_EV_MAX' are free for user events
[source,c] @@ -115,6 +117,8 @@ union GP_EventValue { struct GP_EventPosAbs abs; /* system event */ struct GP_EventSys sys; + /* timer event */ + GP_Timer *tmr; };
struct GP_EventPosRel { @@ -145,7 +149,7 @@ events has no value at all. * The relative coordinates are used for 'GP_EV_REL_POS' and absolute coordinates for 'GP_EV_ABS_POS'.
-* The key event value is used for keypresses, additionally it holds the key +* The key event value is used for key-presses, additionally it holds the key value mapped to ASCII if conversion is applicable otherwise it's set to zero. You should consult the header 'input/GP_Event.h' for the comprehensive list of key values. @@ -158,15 +162,17 @@ higher resolution). So for example 'LEFTSHIFT' on the image is .GFXprim key names without the 'GP_KEY_' prefix. image::keyboard.svg["Keyboard Layout",width=800,link="keyboard.svg"]
-* And finally the system event is used with 'GP_EV_SYS_RESIZE' and informs you +* The system event is used with 'GP_EV_SYS_RESIZE' and informs you of the new window size.
+* The value of timer event is simply pointer to the expired timer. + The 'dev_id' is not used at the moment and may be removed.
The timeval structure 'time' holds time when the event was created (or received by GFXprim input driver).
-The 'cursor_x' and 'cursor_y' holds current pointer coodinates. (All relative +The 'cursor_x' and 'cursor_y' holds current pointer coordinates. (All relative and absolute events are mixed together to compute current cursor position.)
The 'key_pressed' is bitflag array of currently pressed keys which is useful @@ -219,3 +225,121 @@ These functions are helpers for setting/getting key pressed bits in the You will mostly need the 'GP_EventGetKey' function to figure out if some of the modificator keys (such as Ctrl or Shift) was pressed at the time the event was received. + +[[Timers]] +Timers +~~~~~~ + +Input layer also implements 'priority queue' (implemented using binary heap) +to store multiple timer events. This part of the code is used in +link:backends.html[backends] where you can simply add timer which gets +processed automatically in the program main loop (while you call the backend +Wait or Poll functions). + +[source,c] +------------------------------------------------------------------------------- +#include <GP.h> +/* or */ +#include <input/GP_Timer.h> + +typedef struct GP_Timer { + /* Heap pointers and number of sons */ + struct GP_Timer *left; + struct GP_Timer *right; + unsigned int sons; + + /* Expiration time */ + uint64_t expires; + /* + * If not zero return value from Callback is ignored and + * timer is rescheduled each time it expires. + */ + uint32_t period; + + /* Timer id, showed in debug messages */ + char id[10]; + + /* + * Timer Callback + * + * If non-zero is returned, the timer is rescheduled to expire + * return value from now. + */ + uint32_t (*Callback)(struct GP_Timer *self); + void *priv; +} GP_Timer; + +#define GP_TIMER_DECLARE(name, expires, period, id, Callback, priv) + ... +------------------------------------------------------------------------------- + +Timers are implemented as a simple structure with a callback, expiration, id +string and internal heap pointers. The priority queue is described simply by +the pointer to the top timer (soonest time to expire). + +The 'priv' pointer is used to pass a user pointer to the callback function. + +The number of timers in the queue is the number of sons of the top timer plus +one. + +The 'GP_TIMER_DECLARE()' creates and initializes timer on the program stack. +The 'name' is the name of the declared timer structure and the rest of the +variables corresponds to the structure members. + +[source,c] +------------------------------------------------------------------------------- +#include <GP.h> +/* or */ +#include <input/GP_Timer.h> + +void GP_TimerQueueDump(GP_Timer *queue); +------------------------------------------------------------------------------- + +Prints the structure of binary heap into stdout, only for debugging. + +[source,c] +------------------------------------------------------------------------------- +#include <GP.h> +/* or */ +#include <input/GP_Timer.h> + +void GP_TimerQueueInsert(GP_Timer **queue, uint64_t now, GP_Timer *timer); +------------------------------------------------------------------------------- + +Inserts timer into the timer priority queue. The timer is scheduled to expire +at `now + timer->expire`. + +[source,c] +------------------------------------------------------------------------------- +#include <GP.h> +/* or */ +#include <input/GP_Timer.h> + +int GP_TimerQueueProcess(GP_Timer **queue, uint64_t now); +------------------------------------------------------------------------------- + +Processes all expired timers (all timers with `timer->expires <= now` are processed). + +Recurrent timers and timers that returned non-zero from callback are reinserted +into the queue with new expiration time. + +Returns number of timers processed. + +[[TimeStamp]] +TimerStamp +~~~~~~~~~~ + +Timestamp provides fast monotonously increasing timestamps in milliseconds. + +Timestamp is used together with link:#Timers[timers]. + +[source,c] +------------------------------------------------------------------------------- +#include <GP.h> +/* or */ +#include <input/GP_TimeStamp.h> + +uint64_t GP_GetTimeStamp(void); +------------------------------------------------------------------------------- + +Returns timestamp (i.e. time elapsed since some point) in milliseconds.
http://repo.or.cz/w/gfxprim.git/commit/4576af9cfc5ff38fb8b5cd804d0f05eb891b8...
commit 4576af9cfc5ff38fb8b5cd804d0f05eb891b83f6 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 21 21:47:32 2013 +0200
spiv: Get rid of the ugly slideshow code, use timers!
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 5f03205..11b8f4b 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -620,7 +620,7 @@ static void sighandler(int signo) fprintf(stderr, "Got signal %in", signo);
- exit(1); + _exit(1); }
static void init_backend(const char *backend_opts) @@ -633,78 +633,6 @@ static void init_backend(const char *backend_opts) } }
-static int alarm_fired = 0; - -static void alarm_handler(int signo) -{ - alarm_fired = 1; -} - -static int wait_for_event(int sleep_msec) -{ - static int sleep_msec_count = 0; - static int alarm_set = 0; - - if (sleep_msec < 0) { - GP_BackendPoll(backend); - usleep(10000); - return 0; - } - - /* We can't sleep on backend fd, because the backend doesn't export it. */ - if (backend->fd < 0) { - GP_BackendPoll(backend); - usleep(10000); - - sleep_msec_count += 10; - - if (sleep_msec_count >= sleep_msec) { - sleep_msec_count = 0; - return 1; - } - - return 0; - } - - /* Initalize select */ - fd_set rfds; - FD_ZERO(&rfds); - - FD_SET(backend->fd, &rfds); - - if (!alarm_set) { - signal(SIGALRM, alarm_handler); - alarm(sleep_msec / 1000); - alarm_fired = 0; - alarm_set = 1; - } - - struct timeval tv = {.tv_sec = sleep_msec / 1000, - .tv_usec = (sleep_msec % 1000) * 1000}; - - int ret = select(backend->fd + 1, &rfds, NULL, NULL, &tv); - - switch (ret) { - case -1: - if (errno == EINTR) - return 1; - - GP_BackendExit(backend); - exit(1); - break; - case 0: - if (alarm_fired) { - alarm_set = 0; - return 1; - } - - return 0; - break; - default: - GP_BackendPoll(backend); - return 0; - } -}
static void init_caches(struct loader_params *params) { @@ -728,11 +656,20 @@ static void init_caches(struct loader_params *params) // params->img_orig_cache = NULL; }
+static uint32_t timer_callback(GP_Timer *self) +{ + struct loader_params *params = self->priv; + + show_image(params, image_list_move(params->img_list, 1)); + + return 0; +} + int main(int argc, char *argv[]) { GP_Context *context = NULL; const char *backend_opts = "X11"; - int sleep_sec = -1; + int sleep_ms = -1; int opt; int shift_flag; GP_PixelType emul_type = GP_PIXEL_UNKNOWN; @@ -755,6 +692,8 @@ int main(int argc, char *argv[]) .img_orig_cache = NULL, };
+ GP_TIMER_DECLARE(timer, 0, 0, "Slideshow", timer_callback, ¶ms); + while ((opt = getopt(argc, argv, "b:ce:fhIPs:r:z:0:1:2:3:4:5:6:7:8:9:")) != -1) { switch (opt) { case 'I': @@ -767,7 +706,7 @@ int main(int argc, char *argv[]) params.use_dithering = 1; break; case 's': - sleep_sec = atoi(optarg); + sleep_ms = atoi(optarg); break; case 'c': params.resampling_method = GP_INTERP_CUBIC_INT; @@ -850,13 +789,15 @@ int main(int argc, char *argv[])
params.show_progress_once = 1; show_image(¶ms, image_list_img_path(list)); - + + if (sleep_ms) { + timer.period = sleep_ms; + GP_BackendAddTimer(backend, &timer); + } + for (;;) { - /* wait for event or a timeout */ - if (wait_for_event(sleep_sec * 1000)) - show_image(¶ms, image_list_move(list, 1)); + GP_BackendWait(backend);
- /* Read and parse events */ GP_Event ev;
while (GP_BackendGetEvent(backend, &ev)) { diff --git a/demos/spiv/spiv_help.c b/demos/spiv/spiv_help.c index 701b5ae..f8d3c40 100644 --- a/demos/spiv/spiv_help.c +++ b/demos/spiv/spiv_help.c @@ -75,7 +75,7 @@ void print_help(void) printf(" -I show image info boxn"); printf(" -P show loading progressn"); printf(" -f use floyd-steinberg ditheringn"); - printf(" -s sec sleep interval in secondsn"); + printf(" -s msec slideshow interval in milisecondsn"); printf(" -c turns on bicubic resampling (experimental)n"); printf(" -e pixel_type turns on backend type emulationn"); printf(" for example -e G1 sets 1-bit grayscalen");
http://repo.or.cz/w/gfxprim.git/commit/2b7cd8c924e4a9b4b0a946d9f5b22067789cf...
commit 2b7cd8c924e4a9b4b0a946d9f5b22067789cf18c Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 21 21:46:34 2013 +0200
build: Update list of exported symbols.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/build/syms/Backend_symbols.txt b/build/syms/Backend_symbols.txt index 74e2967..7d5128e 100644 --- a/build/syms/Backend_symbols.txt +++ b/build/syms/Backend_symbols.txt @@ -16,8 +16,11 @@ GP_BackendResize GP_BackendResizeAck GP_BackendUpdateRectXYXY GP_BackendFlip +GP_BackendWait +GP_BackendPoll GP_BackendWaitEvent GP_BackendPollEvent +GP_BackendAddTimer
GP_InputDriverX11EventPut GP_InputDriverX11Init diff --git a/build/syms/Input_symbols.txt b/build/syms/Input_symbols.txt index 2062806..700dedc 100644 --- a/build/syms/Input_symbols.txt +++ b/build/syms/Input_symbols.txt @@ -24,3 +24,9 @@ GP_EventQueuePushKey GP_EventQueuePushAbs GP_EventQueuePush GP_EventQueuePushResize + +GP_TimerQueueDump +GP_TimerQueueProcess +GP_TimerQueueInsert + +GP_GetTimeStamp
http://repo.or.cz/w/gfxprim.git/commit/b26b80ae54cda6dc76f1b002e221ae62dd598...
commit b26b80ae54cda6dc76f1b002e221ae62dd5989de Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 21 21:45:16 2013 +0200
backends: Add support for timers to backends.
Now you can add any number of timers to backend and the timers are processed while you call Wait or Poll.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/include/backends/GP_Backend.h b/include/backends/GP_Backend.h index 792d603..e623eda 100644 --- a/include/backends/GP_Backend.h +++ b/include/backends/GP_Backend.h @@ -45,8 +45,7 @@ #include "core/GP_Context.h"
#include "input/GP_EventQueue.h" - -struct GP_Backend; +#include "input/GP_Timer.h"
typedef struct GP_Backend { /* @@ -136,6 +135,11 @@ typedef struct GP_Backend { */ struct GP_EventQueue event_queue;
+ /* + * Priority queue for timers. + */ + struct GP_Timer *timers; + /* Backed private data */ char priv[]; } GP_Backend; @@ -180,10 +184,7 @@ static inline void GP_BackendExit(GP_Backend *backend) /* * Polls backend, the events are filled into event queue. */ -static inline void GP_BackendPoll(GP_Backend *backend) -{ - backend->Poll(backend); -} +void GP_BackendPoll(GP_Backend *self);
/* * Poll and GetEvent combined. @@ -193,10 +194,7 @@ int GP_BackendPollEvent(GP_Backend *self, GP_Event *ev); /* * Waits for backend events. */ -static inline void GP_BackendWait(GP_Backend *backend) -{ - backend->Wait(backend); -} +void GP_BackendWait(GP_Backend *self);
/* * Wait and GetEvent combined. @@ -204,6 +202,16 @@ static inline void GP_BackendWait(GP_Backend *backend) int GP_BackendWaitEvent(GP_Backend *self, GP_Event *ev);
/* + * Adds timer to backend. + * + * If timer Callback is NULL a timer event is pushed into + * the backend event queue once timer expires. + * + * See input/GP_Timer.h for more information about timers. + */ +void GP_BackendAddTimer(GP_Backend *self, GP_Timer *timer); + +/* * Sets backend caption, if supported. * * When setting caption is not possible/implemented non zero is returned. diff --git a/include/input/GP_Event.h b/include/input/GP_Event.h index 3159ad0..fa71742 100644 --- a/include/input/GP_Event.h +++ b/include/input/GP_Event.h @@ -37,6 +37,8 @@ #include <stdint.h> #include <sys/time.h>
+#include "input/GP_Timer.h" + #define GP_EVENT_QUEUE_SIZE 32
#define GP_EVENT_KEYMAP_BYTES 36 @@ -46,7 +48,8 @@ enum GP_EventType { GP_EV_REL = 2, /* relative event */ GP_EV_ABS = 3, /* absolute event */ GP_EV_SYS = 4, /* system events window close, resize... */ - GP_EV_MAX = 4, /* maximum, greater values are free */ + GP_EV_TMR = 5, /* timer expired event */ + GP_EV_MAX = 5, /* maximum, greater values are free */ };
enum GP_EventKeyCode { @@ -264,6 +267,8 @@ union GP_EventValue { struct GP_EventPosAbs abs; /* system event */ struct GP_EventSys sys; + /* timer event */ + GP_Timer *tmr; };
typedef struct GP_Event { diff --git a/libs/backends/GP_Backend.c b/libs/backends/GP_Backend.c index 9d80d55..c216177 100644 --- a/libs/backends/GP_Backend.c +++ b/libs/backends/GP_Backend.c @@ -20,10 +20,16 @@ * * *****************************************************************************/
+#include <inttypes.h> +#include <poll.h> + #include "core/GP_Common.h" #include "core/GP_Transform.h" #include "core/GP_Debug.h"
+#include "input/GP_EventQueue.h" +#include "input/GP_TimeStamp.h" + #include "backends/GP_Backend.h"
void GP_BackendFlip(GP_Backend *backend) @@ -103,6 +109,93 @@ int GP_BackendResizeAck(GP_Backend *self) return 0; }
+static uint32_t pushevent_callback(GP_Timer *self) +{ + GP_Event ev; + + ev.type = GP_EV_TMR; + ev.val.tmr = self; + + GP_EventQueuePut(self->priv, &ev); + + return 0; +} + +void GP_BackendAddTimer(GP_Backend *self, GP_Timer *timer) +{ + if (timer->Callback == NULL) { + timer->Callback = pushevent_callback; + timer->priv = &self->event_queue; + } + + GP_TimerQueueInsert(&self->timers, GP_GetTimeStamp(), timer); +} + +void GP_BackendPoll(GP_Backend *self) +{ + self->Poll(self); + + if (self->timers) + GP_TimerQueueProcess(&self->timers, GP_GetTimeStamp()); +} + +static void wait_timers_fd(GP_Backend *self, uint64_t now) +{ + int timeout; + + timeout = self->timers->expires - now; + + struct pollfd fd = {.fd = self->fd, .events = POLLIN, fd.revents = 0}; + + if (poll(&fd, 1, timeout)) + self->Poll(self); + + now = GP_GetTimeStamp(); + + GP_TimerQueueProcess(&self->timers, now); +} + +/* + * Polling for backends that does not expose FD to wait on (namely SDL). + */ +static void wait_timers_poll(GP_Backend *self) +{ + for (;;) { + uint64_t now = GP_GetTimeStamp(); + + if (GP_TimerQueueProcess(&self->timers, now)) + return; + + self->Poll(self); + + if (GP_BackendEventsQueued(self)) + return; + + usleep(10000); + } +} + +void GP_BackendWait(GP_Backend *self) +{ + uint64_t now = GP_GetTimeStamp(); + + if (self->timers) { + /* Get rid of possibly expired timers */ + if (GP_TimerQueueProcess(&self->timers, now)) + return; + + /* Wait for events or timer expiration */ + if (self->fd != -1) + wait_timers_fd(self, now); + else + wait_timers_poll(self); + + return; + } + + self->Wait(self); +} + int GP_BackendWaitEvent(GP_Backend *self, GP_Event *ev) { int ret; diff --git a/libs/backends/GP_BackendVirtual.c b/libs/backends/GP_BackendVirtual.c index 41e947a..7ea1238 100644 --- a/libs/backends/GP_BackendVirtual.c +++ b/libs/backends/GP_BackendVirtual.c @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
@@ -150,6 +150,7 @@ GP_Backend *GP_BackendVirtualInit(GP_Backend *backend, self->Poll = backend->Poll ? virt_poll : NULL; self->Wait = backend->Wait ? virt_wait : NULL; self->SetAttributes = backend->SetAttributes ? virt_set_attrs : NULL; + self->timers = NULL;
GP_EventQueueInit(&self->event_queue, backend->context->w, backend->context->h, 0); diff --git a/libs/backends/GP_LinuxFB.c b/libs/backends/GP_LinuxFB.c index b203109..49566aa 100644 --- a/libs/backends/GP_LinuxFB.c +++ b/libs/backends/GP_LinuxFB.c @@ -313,6 +313,7 @@ GP_Backend *GP_BackendLinuxFBInit(const char *path, int flag) backend->Poll = flag ? fb_poll : NULL; backend->Wait = flag ? fb_wait : NULL; backend->fd = fb->con_fd; + backend->timers = NULL;
GP_EventQueueInit(&backend->event_queue, vscri.xres, vscri.yres, 0);
diff --git a/libs/backends/GP_SDL.c b/libs/backends/GP_SDL.c index 4dcfeb3..1e73ecf 100644 --- a/libs/backends/GP_SDL.c +++ b/libs/backends/GP_SDL.c @@ -200,6 +200,7 @@ static struct GP_Backend backend = { .fd = -1, .Poll = sdl_poll, .Wait = sdl_wait, + .timers = NULL, };
static void sdl_exit(struct GP_Backend *self __attribute__((unused))) diff --git a/libs/backends/GP_X11.c b/libs/backends/GP_X11.c index a95e626..b0aff6d 100644 --- a/libs/backends/GP_X11.c +++ b/libs/backends/GP_X11.c @@ -618,6 +618,7 @@ GP_Backend *GP_BackendX11Init(const char *display, int x, int y, backend->SetAttributes = x11_set_attributes; backend->ResizeAck = x11_resize_ack; backend->fd = XConnectionNumber(win->dpy); + backend->timers = NULL;
return backend; err1: diff --git a/libs/input/GP_Event.c b/libs/input/GP_Event.c index 7bfb9f8..d7ec7cd 100644 --- a/libs/input/GP_Event.c +++ b/libs/input/GP_Event.c @@ -148,6 +148,9 @@ void GP_EventDump(struct GP_Event *ev) case GP_EV_SYS: dump_sys(ev); break; + case GP_EV_TMR: + printf("Timer %s expiredn", ev->val.tmr->id); + break; default: printf("Unknown %un", ev->type); }
http://repo.or.cz/w/gfxprim.git/commit/32a00d3651aa79bc3db01c0f2ce4e1c89c6e3...
commit 32a00d3651aa79bc3db01c0f2ce4e1c89c6e3c97 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 21 19:23:35 2013 +0200
input: Add GP_GetTimeStamp() function.
The function returns number of miliseconds from some point (boot of the machine, start of the program, 1. 1. 1970 or anything else).
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/configure b/configure index 36450a1..107db2d 100755 --- a/configure +++ b/configure @@ -265,7 +265,7 @@ def write_gfxprim_config(cfg, libs): f.write('t--list-modules) echo "%s"; exit 0;;n' % ' '.join(modules)) f.write('t--cflags) echo -n "-I/usr/include/GP/%s";;n' % libs.get_cflags('core')) - f.write('t--libs) echo -n "-lGP -lm %s ";;n' % libs.get_linker_flags('core')) + f.write('t--libs) echo -n "-lGP -lrt -lm %s ";;n' % libs.get_linker_flags('core'))
# ldflags for specific modules for i in modules: diff --git a/include/input/GP_Input.h b/include/input/GP_Input.h index 4c67e12..cd3e8ca 100644 --- a/include/input/GP_Input.h +++ b/include/input/GP_Input.h @@ -33,4 +33,9 @@ */ #include "input/GP_Timer.h"
+/* + * Timestamp. + */ +#include "input/GP_TimeStamp.h" + #endif /* INPUT_GP_INPUT_H */ diff --git a/include/input/GP_Input.h b/include/input/GP_TimeStamp.h similarity index 88% copy from include/input/GP_Input.h copy to include/input/GP_TimeStamp.h index 4c67e12..32bd575 100644 --- a/include/input/GP_Input.h +++ b/include/input/GP_TimeStamp.h @@ -20,17 +20,17 @@ * * *****************************************************************************/
-#ifndef INPUT_GP_INPUT_H -#define INPUT_GP_INPUT_H - /* - * Base GP_Event definitions. - */ -#include "input/GP_Event.h" + + Returns monotonously incrementing timestamps in milliseconds.
-/* - * Timers and priority queue */ -#include "input/GP_Timer.h"
-#endif /* INPUT_GP_INPUT_H */ +#ifndef INPUT_GP_TIME_STAMP_H +#define INPUT_GP_TIME_STAMP_H + +#include <stdint.h> + +uint64_t GP_GetTimeStamp(void); + +#endif /* INPUT_GP_TIME_STAMP_H */ diff --git a/libs/input/GP_TimeStamp.c b/libs/input/GP_TimeStamp.c new file mode 100644 index 0000000..4185ee6 --- /dev/null +++ b/libs/input/GP_TimeStamp.c @@ -0,0 +1,91 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +#include <errno.h> +#include <string.h> +#include <time.h> + +#include "core/GP_Common.h" +#include "core/GP_Debug.h" + +#include "input/GP_TimeStamp.h" + +#define MS_IN_US 1000000 + +/* + * Chooses fastest clock with milisecond resolution. + */ +static int choose_clock(clockid_t *clock) +{ + struct timespec ts; + +#ifdef CLOCK_MONOTONIC_COARSE + GP_DEBUG(1, "Trying CLOCK_MONOTONIC_COARSE"); + + if (clock_getres(CLOCK_MONOTONIC_COARSE, &ts)) { + GP_DEBUG(1, "CLOCK_MONOTONIC_COARSE: %s", strerror(errno)); + } else { + GP_DEBUG(1, "CLOCK_MONOTONIC_COARSE resolution is %lis %lins", + (long)ts.tv_sec, ts.tv_nsec); + + /* Depends on CONFIG_HZ */ + if (ts.tv_sec == 0 && ts.tv_nsec <= MS_IN_US) { + *clock = CLOCK_MONOTONIC_COARSE; + return 0; + } + } +#endif + + if (clock_getres(CLOCK_MONOTONIC, &ts)) { + GP_DEBUG(1, "CLOCK_MONOTONIC: %s", strerror(errno)); + return 1; + } + + GP_DEBUG(1, "CLOCK_MONOTONIC resulution is %lis %lins", + (long)ts.tv_sec, ts.tv_nsec); + + if (ts.tv_sec == 0 && ts.tv_nsec <= MS_IN_US) { + *clock = CLOCK_MONOTONIC; + return 0; + } + + GP_DEBUG(1, "No suitable clock id found."); + //TODO: Fallback to gettimeofday? + + return 1; +} + +uint64_t GP_GetTimeStamp(void) +{ + struct timespec ts; + static clockid_t clock = -1; + + if (clock == -1) + choose_clock(&clock); + + if (clock_gettime(clock, &ts)) { + GP_ABORT("clock_gettime(%i) failed unexpectedly: %s", + clock, strerror(errno)); + } + + return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / MS_IN_US; +}
http://repo.or.cz/w/gfxprim.git/commit/cf00485b00ae80031789a382a764e21cd70ec...
commit cf00485b00ae80031789a382a764e21cd70ec706 Author: Cyril Hrubis metan@ucw.cz Date: Thu Jun 20 23:28:32 2013 +0200
input: Add timers and timer priority queues.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/demos/c_simple/Makefile b/demos/c_simple/Makefile index e086f75..e430cc4 100644 --- a/demos/c_simple/Makefile +++ b/demos/c_simple/Makefile @@ -18,7 +18,7 @@ APPS=backend_example loaders_example loaders filters_symmetry gfx_koch v4l2_show v4l2_grab convolution weighted_median shapetest koch input_example fileview linetest randomshapetest fonttest loaders_register blittest textaligntest abort sin_AA x11_windows- debug_handler gaussian_noise byte_utils version pretty_print + debug_handler gaussian_noise byte_utils version pretty_print timers
ifeq ($(HAVE_LIBSDL),yes) APPS+=SDL_glue diff --git a/include/input/GP_Input.h b/demos/c_simple/timers.c similarity index 61% copy from include/input/GP_Input.h copy to demos/c_simple/timers.c index 80ebe2b..112223a 100644 --- a/include/input/GP_Input.h +++ b/demos/c_simple/timers.c @@ -16,16 +16,52 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
-#ifndef INPUT_GP_INPUT_H -#define INPUT_GP_INPUT_H - /* - * Base GP_Event definitions. + + Simple example how to use raw timer priority queue. + */ -#include "input/GP_Event.h"
-#endif /* INPUT_GP_INPUT_H */ +#include <GP.h> + +uint32_t callback1() +{ + return 0; +} + +uint32_t callback3() +{ + return random() % 30 + 1; +} + +int main(void) +{ + GP_TIMER_DECLARE(oneshot, 30, 0, "Oneshot", callback1, NULL); + GP_TIMER_DECLARE(recurrent, 0, 4, "Recurrent", callback1, NULL); + GP_TIMER_DECLARE(random, 10, 0, "Random", callback3, NULL); + GP_Timer *queue = NULL; + uint64_t now; + int ret; + + GP_SetDebugLevel(10); + + GP_TimerQueueInsert(&queue, 0, &oneshot); + GP_TimerQueueInsert(&queue, 0, &recurrent); + GP_TimerQueueInsert(&queue, 0, &random); + + for (now = 0; now < 100; now += 3) { + printf("NOW %un", (unsigned int) now); + printf("-------------------------------------n"); + ret = GP_TimerQueueProcess(&queue, now); + printf("Processed %i timer eventsn", ret); + printf("--------------------------------------n"); + GP_TimerQueueDump(queue); + printf("--------------------------------------nn"); + } + + return 0; +} diff --git a/include/input/GP_Input.h b/include/input/GP_Input.h index 80ebe2b..4c67e12 100644 --- a/include/input/GP_Input.h +++ b/include/input/GP_Input.h @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
@@ -28,4 +28,9 @@ */ #include "input/GP_Event.h"
+/* + * Timers and priority queue + */ +#include "input/GP_Timer.h" + #endif /* INPUT_GP_INPUT_H */ diff --git a/include/input/GP_Timer.h b/include/input/GP_Timer.h new file mode 100644 index 0000000..6026268 --- /dev/null +++ b/include/input/GP_Timer.h @@ -0,0 +1,93 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +/* + + Timers and priority queue implementation. + + */ + +#ifndef INPUT_GP_TIMER_H +#define INPUT_GP_TIMER_H + +#include <stdint.h> + +typedef struct GP_Timer { + /* Heap pointers and number of sons */ + struct GP_Timer *left; + struct GP_Timer *right; + unsigned int sons; + + /* Expiration time */ + uint64_t expires; + /* + * If not zero return value from Callback is ignored and + * timer is rescheduled each time it expires. + */ + uint32_t period; + + /* Timer id, showed in debug messages */ + char id[10]; + + /* + * Timer Callback + * + * If non-zero is returned, the timer is rescheduled to expire + * return value from now. + */ + uint32_t (*Callback)(struct GP_Timer *self); + void *priv; +} GP_Timer; + +#define GP_TIMER_DECLARE(name, texpires, tperiod, tid, tCallback, tpriv) + GP_Timer name = { + .expires = texpires, + .period = tperiod, + .id = tid, + .Callback = tCallback, + .priv = tpriv + } + +/* + * Prints the structrue of binary heap into stdout, only for debugging. + */ +void GP_TimerQueueDump(GP_Timer *queue); + +/* + * Inserts timer into the timer priority queue. + */ +void GP_TimerQueueInsert(GP_Timer **queue, uint64_t now, GP_Timer *timer); + +/* + * Removes timer from timer queue. Returns NULL if id was not found. + */ +GP_Timer GP_TimerQueueRemove(GP_Timer *queue, GP_Timer *timer); +GP_Timer GP_TimerQueueRemoveById(GP_Timer *queue, const char *id); + +/* + * Processes queue, all timers with expires <= now are processed. + * + * Returns number of timers processed. + */ +int GP_TimerQueueProcess(GP_Timer **queue, uint64_t now); + +#endif /* INPUT_GP_TIMER_H */ diff --git a/libs/input/GP_Timer.c b/libs/input/GP_Timer.c new file mode 100644 index 0000000..39f63f5 --- /dev/null +++ b/libs/input/GP_Timer.c @@ -0,0 +1,263 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +#include <inttypes.h> +#include <string.h> + +#include "core/GP_Debug.h" +#include "core/GP_Common.h" + +#include "input/GP_Timer.h" + +static void dump_level(GP_Timer *heap, unsigned int level, unsigned int cur) +{ + if (level == cur) { + if (heap) + printf("[%9s %8"PRIu64"] ", heap->id, heap->expires); + else + printf(" "); + return; + } + + dump_level(heap ? heap->left : NULL, level, cur+1); + dump_level(heap ? heap->right : NULL , level, cur+1); +} + +void GP_TimerQueueDump(GP_Timer *heap) +{ + unsigned int i, j = 0; + + if (heap == NULL) + return; + + for (i = 1; heap->sons + 1 >= i; i = i*2) { + dump_level(heap, j++, 0); + printf("n"); + } +} + +static int timer_cmp(GP_Timer *t1, GP_Timer *t2) +{ + return t1->expires > t2->expires; +} + +/* + * Returns true if subtree is well balanced i.e. we have 2^n - 2 sons + */ +static int well_balanced(unsigned int sons) +{ + switch (sons) { + case 0: + case 2: + case 6: + case 15: + case 30: + case 62: + case 126: + case 254: + case 510: + case 1022: + case 2046: + case 4092: + case 8190: + case 16382: + case 32766: + return 1; + default: + return 0; + } +} + +static GP_Timer *swap_left(GP_Timer *heap) +{ + GP_Timer *left = heap->left; + + heap->left = left->left; + left->left = heap; + GP_SWAP(heap->right, left->right); + GP_SWAP(heap->sons, left->sons); + + return left; +} + +static GP_Timer *swap_right(GP_Timer *heap) +{ + GP_Timer *right = heap->right; + + heap->right = right->right; + right->right = heap; + GP_SWAP(heap->left, right->left); + GP_SWAP(heap->sons, right->sons); + + return right; +} + +/* + * Inserts timer into binary heap. Returns new root for the tree. + */ +static GP_Timer *insert(GP_Timer *heap, GP_Timer *timer) +{ + if (heap == NULL) { + timer->left = NULL; + timer->right = NULL; + timer->sons = 0; + return timer; + } + + heap->sons++; + + if (!heap->left || !well_balanced(heap->left->sons) || + (heap->right && heap->left->sons == heap->right->sons)) { + + heap->left = insert(heap->left, timer); + + if (timer_cmp(heap, heap->left)) + return swap_left(heap); + } else { + + heap->right = insert(heap->right, timer); + + if (timer_cmp(heap, heap->right)) + return swap_right(heap); + } + + return heap; +} + +static GP_Timer *rem_last(GP_Timer *heap, GP_Timer **last) +{ + if (!heap->left) { + *last = heap; + return NULL; + } + + if (!well_balanced(heap->left->sons) || + !heap->right || (heap->right->sons < heap->left->sons/2)) + heap->left = rem_last(heap->left, last); + else + heap->right = rem_last(heap->right, last); + + heap->sons--; + + return heap; +} + +static GP_Timer *buble_down(GP_Timer *heap) +{ + GP_Timer *right = heap->right; + GP_Timer *left = heap->left; + + /* Make sure we choose smaller one */ + if (right && left && timer_cmp(right, left)) + right = NULL; + + if (right && timer_cmp(heap, right)) { + swap_right(heap); + right->right = buble_down(heap); + return right; + } + + if (left && timer_cmp(heap, left)) { + swap_left(heap); + left->left = buble_down(heap); + return left; + } + + return heap; +} + +static GP_Timer *pop(GP_Timer *heap) +{ + GP_Timer *last; + + if (heap == NULL) + return NULL; + + heap = rem_last(heap, &last); + + if (!heap) + return NULL; + + last->left = heap->left; + last->right = heap->right; + last->sons = heap->sons; + + return buble_down(last); +} + +void GP_TimerQueueInsert(GP_Timer **heap, uint64_t now, GP_Timer *timer) +{ + uint32_t after = timer->period ? timer->period : timer->expires; + uint64_t expires = now + after; + + GP_DEBUG(3, "Inserting timer %s (now is %"PRIu64") expires after %" + PRIu32" at %"PRIu64, timer->id, now, after, expires); + + timer->expires = expires; + + *heap = insert(*heap, timer); +} + +static GP_Timer *process_top(GP_Timer *heap, uint64_t now) +{ + GP_Timer *timer = heap; + uint32_t ret, period; + + GP_DEBUG(3, "Timer %s expired at %"PRIu64" now is %"PRIu64, + timer->id, timer->expires, now); + + heap = pop(heap); + + period = timer->period; + ret = timer->Callback(timer); + + if (period) + ret = period; + + if (ret) { + timer->expires = now + ret; + GP_DEBUG(3, "Rescheduling %stimer %s (now is %"PRIu64") after %" + PRIu32" expires at %"PRIu64, + period ? "periodic " : "", + timer->id, now, ret, timer->expires); + heap = insert(heap, timer); + } + + return heap; +} + +int GP_TimerQueueProcess(GP_Timer **heap, uint64_t now) +{ + int ret = 0; + + for (;;) { + if (*heap == NULL) + return ret; + + if ((*heap)->expires <= now) { + *heap = process_top(*heap, now); + ret++; + } else { + return ret; + } + } +}
http://repo.or.cz/w/gfxprim.git/commit/ec6f972853a8eec5ccea7df42077ab6745938...
commit ec6f972853a8eec5ccea7df42077ab6745938ccc Author: Cyril Hrubis metan@ucw.cz Date: Wed Jun 19 23:18:34 2013 +0200
doc: loaders, environment_variables: Update.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/doc/environment_variables.txt b/doc/environment_variables.txt index dec32e7..26d7209 100644 --- a/doc/environment_variables.txt +++ b/doc/environment_variables.txt @@ -4,6 +4,7 @@ Environment Variables The GFXprim library behavior may be changed by a couple of environment variables:
+[[GP_THREADS]] GP_THREADS ~~~~~~~~~~
@@ -21,10 +22,39 @@ bellow: | >=2 | Use N threads unless the image buffer is too small. |=============================================================================
+[[GP_DEBUG]] GP_DEBUG ~~~~~~~~
The 'GP_DEBUG' environment variable may be used to set library debug level. +See link:debug.html[debug messages] description for more information. + The variable and its value is used only once at the time first debug message is about to be printed.
+The debug level is an integer number, the higher it is the more verbose +messages are printed. Current the maximum used in GFXprim sources is 4, this +may change in the future. Use 'GP_DEBUG=10' to enable all debug messages for +sure. + +The output is, by default, written to 'stderr' and will look like: +------------------------------------------------------------------------------ +1: GP_Debug.c:GP_DebugPrint():67: Using debug level GP_DEBUG=10 from enviroment variable +1: GP_Debug.c:GP_DebugPrint():71: GFXprim library version 1.0.0-rc0 +1: GP_X11_Conn.h:x11_open():43: Opening X11 display '(null)' +1: GP_InputDriverX11.c:init_table():154: Initializing X11 KeyCode table + 3: GP_InputDriverX11.c:init_table():174: Mapping Key 'Up' KeySym 'Up' (65362) to KeyCode 111 +... +1: GP_Loader.c:loader_by_filename():222: Loading file by filename extension 'pgm' +1: GP_Loader.c:loader_by_extension():198: Found loader 'Netpbm portable Graymap' +1: GP_PNM.c:load_header():244: Have header P2 (ASCII encoded PGM) 24x7 depth=15 +1: GP_Context.c:GP_ContextAlloc():62: Allocating context 24 x 7 - G4 + 4: GP_X11.c:x11_update_rect():71: Updating rect 222x458-418x479 + 4: GP_X11.c:x11_update_rect():71: Updating rect 214x458-426x479 + 2: GP_Blit.c:GP_BlitXYXY_Clipped():129: Blitting 23x6, available 332x244 + 2: GP_Blit.c:GP_BlitXYXY_Clipped():139: Blitting 0x0->23x6 in 24x7 to 308x236 in 640x480 + 3: GP_X11.c:x11_set_attributes():225: Setting window caption to 'Spiv ~ test.pgm 1:1.000' + 4: GP_X11.c:x11_flip():91: Flipping context +1: GP_Context.c:GP_ContextFree():102: Freeing context (0x7f5008000b60) +1: GP_X11_Conn.h:x11_close():72: Closing X11 display +------------------------------------------------------------------------------ diff --git a/doc/loaders.txt b/doc/loaders.txt index 907a171..95eb780 100644 --- a/doc/loaders.txt +++ b/doc/loaders.txt @@ -3,8 +3,8 @@ Context loaders This part of GFXprim library aims to create API to load and save images from/to common image file formats.
-Currently we support JPEG, PNG and some PNM images for loading and saving and -BMP, GIF and PSP for loading. +Currently we support JPEG, PNG, BPM and PNM images for loading and saving and +GIF and PSP for loading.
Loaders API ~~~~~~~~~~~ @@ -30,11 +30,11 @@ The possible 'errno' values are:
* 'ENOSYS' if GFXprim wasn't compiled with particular library support * 'ENOMEM' if returned by +malloc()+ -* 'EIO' invalid image data (wrong signature, header or image data) +* 'EIO', 'EINVAL' invalid image data (wrong signature, wrong or too short header or image data) * 'ECANCELED' action canceled by returning non-zero from within a callback
You can get more information about the error condition by turning on GFXprim -debug messages. +link:environment_variables.html#GP_DEBUG[debug messages].
Image Loader ~~~~~~~~~~~~ @@ -62,7 +62,7 @@ matching. If image signature is found particular image loader it is called and the result is returned.
If file extension disagrees with file signature a warning is printed into the -stdout. +'stderr'.
[source,c] ------------------------------------------------------------------------------- @@ -195,8 +195,6 @@ PNG Loader ~~~~~~~~~~ The 'PNG' image support is implemented by the libpng library.
-NOTE: PNG images with alpha channel are not supported yet. - [source,c] ------------------------------------------------------------------------------- #include <loaders/GP_PNG.h> @@ -404,7 +402,7 @@ BMP Loader ~~~~~~~~~~
The 'BMP' loading support is nearly complete the only missing features should -be fancy RGB compressions and RLE support. +be exotic RGB compressions (RGB101010 for example) and RLE4 support.
[source,c] ------------------------------------------------------------------------------- @@ -437,8 +435,6 @@ file. The context, to store the image to, is allocated. The loading process could by aborted by a callback, in such case all memory is freed and the call returns 'NULL' and 'errno' is set to 'ECANCELED'.
-Currently this function loads only first image from the 'GIF' container. - [source,c] ------------------------------------------------------------------------------- #include <loaders/GP_BMP.h> @@ -451,6 +447,17 @@ GP_Context *GP_LoadBMP(const char *src_path, GP_ProgressCallback *callback); Same as above but takes path to the file as a parameter and check for the signature. Basically this combines both of the calls above.
+[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_BMP.h> +/* or */ +#include <GP.h> + +int GP_SaveBMP(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Saves 'RGB888' (24 bit RGB) image into BMP bitmap.
[source,c] ------------------------------------------------------------------------------- @@ -501,7 +508,7 @@ Reads 'PSP' image into a context. GP_Context *GP_LoadPSP(const char *src_path, GP_ProgressCallback *callback); -------------------------------------------------------------------------------
-Same as above but takes path to the file as a parameter and check for the +Same as above but takes path to the file as a parameter and checks for the signature. Basically this combines both of the calls above.
[source,c] @@ -515,8 +522,95 @@ int GP_MatchPSP(const void *buf);
Matches a PSP signature.
-PBM, PGM, PPM -~~~~~~~~~~~~~ +PNM +~~~ + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PNM.h> +/* or */ +#include <GP.h> + +GP_Context *GP_LoadPBM(const char *src_path, GP_ProgressCallback *callback); + +GP_Context *GP_LoadPGM(const char *src_path, GP_ProgressCallback *callback); + +GP_Context *GP_LoadPPM(const char *src_path, GP_ProgressCallback *callback); + +GP_Context *GP_LoadPNM(const char *src_path, GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Loads either ASCII or Rawbits (binary) PBM, PGM and PPM. + +The PNM can load all of them i.e. PBM, PGM and PPM. + + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PNM.h> +/* or */ +#include <GP.h> + +GP_Context *GP_SavePBM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Saves 'G1' (1 bit grayscale) image into ASCII PBM. + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PNM.h> +/* or */ +#include <GP.h> + +GP_Context *GP_SavePGM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Saves 'G1', 'G2', 'G4' and 'G8' (1, 2, 4 and 8 bit grayscale) image into ASCII +PGM. + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PNM.h> +/* or */ +#include <GP.h> + +GP_Context *GP_SavePPM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Saves 'RGB888' (24 bit RGB) image into ASCII PPM. + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PNM.h> +/* or */ +#include <GP.h> + +GP_Context *GP_SavePNM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback); +------------------------------------------------------------------------------- + +Saves 'G1', 'G2', 'G4' and 'G8' (1, 2, 4, 8 bit grayscale) or 'RGB888' (24 bit +RGB) image into ASCII PNM. + +[source,c] +------------------------------------------------------------------------------- +#include <loaders/GP_PNM.h> +/* or */ +#include <GP.h> + +int GP_MatchPBM(const void *buf); + +int GP_MatchPGM(const void *buf); + +int GP_MatchPPM(const void *buf); + +int GP_MatchPNM(const void *buf); +------------------------------------------------------------------------------- + +Matches either ASCII or Rawbits (binary) PBM, PGM and PPM. + +The PNM matches all of them i.e. PBM, PGM and PPM.
-There is a code do load and write 'PBM', 'PGM' and 'PPM' images too. However -it's not finished and its API is outdated. Use at your own risk.
http://repo.or.cz/w/gfxprim.git/commit/d9a8b27f7b932cc340d5d0251ab292fe38821...
commit d9a8b27f7b932cc340d5d0251ab292fe388216a7 Author: Cyril Hrubis metan@ucw.cz Date: Wed Jun 19 00:15:03 2013 +0200
libs: loaders: GP_Loader.c: Cleanup.
Get finally rid of the big piece of old code.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c index fb1bee0..e86c39a 100644 --- a/libs/loaders/GP_Loader.c +++ b/libs/loaders/GP_Loader.c @@ -204,10 +204,9 @@ static struct GP_Loader *loader_by_extension(const char *ext) return NULL; }
-static struct GP_Loader *loader_by_filename(const char *path) +static const char *get_ext(const char *path) { size_t len = strlen(path); - const char *ext; int i;
for (i = len - 1; i >= 0; i--) @@ -217,7 +216,15 @@ static struct GP_Loader *loader_by_filename(const char *path) if (path[i] != '.') return NULL;
- ext = path + i + 1; + return path + i + 1; +} + +static struct GP_Loader *loader_by_filename(const char *path) +{ + const char *ext = get_ext(path); + + if (ext == NULL) + return NULL;
GP_DEBUG(1, "Loading file by filename extension '%s'", ext);
@@ -265,18 +272,15 @@ err0:
GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback) { - int saved_errno; + int err; struct stat st; if (access(src_path, R_OK)) { - - saved_errno = errno; - + err = errno; GP_DEBUG(1, "Failed to access file '%s' : %s", src_path, strerror(errno)); - errno = saved_errno; - + errno = err; return NULL; }
@@ -322,139 +326,31 @@ GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback) return NULL; }
-enum GP_ImageFmt { - GP_FMT_UNKNOWN, - GP_FMT_PNG, - GP_FMT_JPG, - GP_FMT_BMP, - GP_FMT_GIF, - GP_FMT_PSP, - GP_FMT_PBM, - GP_FMT_PGM, - GP_FMT_PPM, -}; - -static enum GP_ImageFmt filename_to_fmt(const char *path) -{ - size_t len = strlen(path); - - if (len < 3) - return GP_FMT_UNKNOWN; - - switch (path[len - 1]) { - /* PNG, JPG, JPEG */ - case 'g': - case 'G': - switch (path[len - 2]) { - case 'n': - case 'N': - if (path[len - 3] == 'p' || - path[len - 3] == 'P') - return GP_FMT_PNG; - break; - case 'p': - case 'P': - if (path[len - 3] == 'j' || - path[len - 3] == 'J') - return GP_FMT_JPG; - break; - case 'e': - case 'E': - if ((path[len - 3] == 'p' || - path[len - 3] == 'P') && - (path[len - 4] == 'j' || - path[len - 4] == 'J')) - return GP_FMT_JPG; - break; - } - break; - /* PPM, PGM, PBM, PNM */ - case 'm': - case 'M': - switch (path[len - 2]) { - case 'b': - case 'B': - if (path[len - 3] == 'p' || - path[len - 3] == 'P') - return GP_FMT_PBM; - break; - case 'g': - case 'G': - if (path[len - 3] == 'p' || - path[len - 3] == 'P') - return GP_FMT_PGM; - break; - case 'p': - case 'P': - if (path[len - 3] == 'p' || - path[len - 3] == 'P') - return GP_FMT_PPM; - break; - } - break; - /* BMP, PSP */ - case 'P': - case 'p': - switch (path[len - 2]) { - case 'M': - case 'm': - if (path[len - 3] == 'B' || - path[len - 3] == 'b') - return GP_FMT_BMP; - break; - case 'S': - case 's': - if (path[len - 3] == 'P' || - path[len - 3] == 'p') - return GP_FMT_PSP; - break; - } - break; - /* GIF */ - case 'F': - case 'f': - switch (path[len - 2]) { - case 'I': - case 'i': - if (path[len - 3] == 'G' || - path[len - 3] == 'g') - return GP_FMT_GIF; - break; - } - break; - } - - return GP_FMT_UNKNOWN; -} - int GP_LoadMetaData(const char *src_path, GP_MetaData *data) { - int saved_errno; - - if (access(src_path, R_OK)) { - - saved_errno = errno; + const char *ext; + int err;
+ if (access(src_path, R_OK)) { + err = errno; GP_DEBUG(1, "Failed to access file '%s' : %s", src_path, strerror(errno)); - - errno = saved_errno; - + errno = err; return 1; }
- enum GP_ImageFmt fmt = filename_to_fmt(src_path); + ext = get_ext(src_path);
- switch (fmt) { - case GP_FMT_JPG: + if (ext == NULL) + goto out; + + if (!strcasecmp(ext, "jpg") || !strcasecmp(ext, "jpeg")) return GP_LoadJPGMetaData(src_path, data); - case GP_FMT_PNG: - return GP_LoadPNGMetaData(src_path, data); - default: - break; - } + if (!strcasecmp(ext, "png")) + return GP_LoadPNGMetaData(src_path, data);
+out: errno = ENOSYS; return 1; }
-----------------------------------------------------------------------
Summary of changes: build/syms/Backend_symbols.txt | 3 + build/syms/Input_symbols.txt | 6 + configure | 2 +- demos/c_simple/Makefile | 2 +- demos/c_simple/{debug_handler.c => timers.c} | 55 ++--- demos/spiv/spiv.c | 101 ++------ demos/spiv/spiv_help.c | 2 +- doc/backends.txt | 19 ++ doc/environment_variables.txt | 30 +++ doc/input.txt | 138 ++++++++++- doc/loaders.txt | 124 ++++++++-- include/backends/GP_Backend.h | 28 ++- include/input/GP_Event.h | 7 +- include/input/GP_Input.h | 12 +- .../version.c => include/input/GP_TimeStamp.h | 15 +- .../input/{GP_InputDriverLinux.h => GP_Timer.h} | 87 ++++--- libs/backends/GP_Backend.c | 93 +++++++ libs/backends/GP_BackendVirtual.c | 3 +- libs/backends/GP_LinuxFB.c | 1 + libs/backends/GP_SDL.c | 1 + libs/backends/GP_X11.c | 1 + libs/input/GP_Event.c | 3 + .../showimage.c => libs/input/GP_TimeStamp.c | 87 ++++--- libs/input/GP_Timer.c | 263 ++++++++++++++++++++ libs/loaders/GP_Loader.c | 156 ++---------- 25 files changed, 878 insertions(+), 361 deletions(-) copy demos/c_simple/{debug_handler.c => timers.c} (67%) copy demos/c_simple/version.c => include/input/GP_TimeStamp.h (88%) copy include/input/{GP_InputDriverLinux.h => GP_Timer.h} (53%) copy demos/c_simple/showimage.c => libs/input/GP_TimeStamp.c (56%) create mode 100644 libs/input/GP_Timer.c
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.