precise timing control of double-buffering flip

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I'm searching a way to ask the time of double-buffering flip.
In order to make a kind of oscilloscope.

At any time t_now, I can access data corresponding to time values before
t_last, where (t_now - t_last) is always < tau_delay_1
I want to draw points using gdk_draw_points
and I know that I can compute them in a time less than tau_delay_2.

Then at time t_now, I want to:
1) compute and draw points using data at time (t_now - tau_delay_1). I 
know to do that
2) see the resulting image at time t_now + tau_delay_2. I don't know
to do that. Please can you help me.

The following program should show a sinusoidal line slowly scrolling to 
the left.
It works, but it suffer a small jitter due to the lack of timing control 
around
gdk_window_process_updates i think.
Also, if the system becomes heavy loaded, the image freeze (this is normal
if tau_delay_2 has a too small value),
and then all the successive images are shown in an accelerated way
I would prefer that out of time images will be not shown.


#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <gtk/gtk.h>

#define NPOINTS 800
#define NSAMP 2000 /*  > NPOINTS + tau_sync/tau_samp */

GTimer *timer;
GdkPoint points[NPOINTS];

struct meas {
    double samp[NSAMP];
    double t_samp;
} data;

double tau_samp = 1.0/44100.0;
double f_sound = 440.1;
double tau_sync = 1.0/440.0;

double min_samp_delay = 1e99;
double max_samp_delay = 0.0;
double max_draw_delay = 0.0;

double timer_elapsed () {
    ulong dummy;
    return g_timer_elapsed (timer, &dummy);
}

gboolean sample_generator () {
    int i;
    data.t_samp = timer_elapsed ();
    double delay;

    for (i=0; i<NSAMP; i++) {
    data.samp[i] = 50.0 * sin (2.0 * M_PI * fmod (f_sound * (data.t_samp 
- (NSAMP - 1 - i)*tau_samp), 1.0));
    }
    delay = timer_elapsed () - data.t_samp;
    if (delay > max_samp_delay) max_samp_delay = delay;
    if (delay < min_samp_delay) min_samp_delay = delay;
    return TRUE;
}

double compute_points () {
    double t = timer_elapsed ();
    double dt;
    int i, ishift;

    dt = data.t_samp - tau_sync * floor (t / tau_sync);
    while (dt < 0.0) dt += tau_sync;
    ishift = NSAMP - NPOINTS - (int) (dt / tau_samp);
    if (NPOINTS + ishift > NSAMP) {
    fprintf (stderr, "NSAMP too low\n");
    abort ();
    }
    for (i = 0; i < NPOINTS; i++) {
    points[i].x = i;
    points[i].y = 75 + (int) data.samp[i + ishift];
    }
    return t;
}

gboolean draw_callback (GtkWidget *widget, GdkEventExpose *event, 
gpointer data) {
    gdk_draw_points(widget->window,
            widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
            points, NPOINTS);   
    return TRUE;
}

gboolean recompute_points(gpointer pDrawingArea) {
    GtkWidget *widget;
    GdkRegion *region;
    double t, delay;

    widget = GTK_WIDGET (pDrawingArea);
    if (!widget->window) return;
    region = gdk_drawable_get_clip_region (widget->window);
   
    gdk_window_invalidate_region (widget->window, region, TRUE);
    t = compute_points ();
    gdk_window_process_updates (widget->window, TRUE);

    delay = timer_elapsed () - t;
    if (delay > max_draw_delay) max_draw_delay = delay;

    return TRUE;
}

gboolean bye () {
    fprintf (stderr, "Min. samp delay = %.6lf\n", min_samp_delay);
    fprintf (stderr, "Max. samp delay = %.6lf\n", max_samp_delay);
    fprintf (stderr, "Max. draw delay = %.6lf\n", max_draw_delay);
    gtk_main_quit ();
    return TRUE;
}

int main(int argc, char **argv) {
    GtkWidget *pWindow;
    GtkWidget *pDrawingArea;

    gtk_init(&argc,&argv);

    pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(pWindow), "destroy", 
G_CALLBACK(gtk_main_quit), NULL);

    pDrawingArea = gtk_drawing_area_new();
    gtk_widget_set_size_request(pDrawingArea, 800,150);
    g_signal_connect (G_OBJECT (pDrawingArea), "expose_event", 
              G_CALLBACK (draw_callback), NULL);

    gtk_container_add(GTK_CONTAINER(pWindow), pDrawingArea);

    timer = g_timer_new ();
    sample_generator ();
    compute_points ();
    gtk_widget_show_all(pWindow);

    g_timeout_add(50, recompute_points, (gpointer) pDrawingArea);
    g_timeout_add(31, sample_generator, NULL);
    g_timeout_add(10000, bye, NULL);

    gtk_main();

    return EXIT_SUCCESS;
}


-- 
FP

_______________________________________________
gtk-list mailing list
gtk-list@xxxxxxxxx
http://mail.gnome.org/mailman/listinfo/gtk-list

[Index of Archives]     [Touch Screen Library]     [GIMP Users]     [Gnome]     [KDE]     [Yosemite News]     [Steve's Art]

  Powered by Linux