#include <gtk/gtk.h>
#include <stdint.h>

double last_update;
GtkWidget *dest;
GdkImage *img;
GdkGC *gc;
int frames = 0;

int queue_draw() {
    gtk_widget_queue_draw(dest);
    return FALSE;
}

double get_timer() {
    GTimeVal now;
    g_get_current_time(&now);
    return  (double)now.tv_sec + ((double)now.tv_usec / 1000000.0f);
}

void on_expose() {
    gdk_draw_image(dest->window, gc, img, 0, 0, 0, 0, img->width, img->height);
    frames++;
}

int draw_func() {
    static int pos = 0; 
    uint32_t *ptr = (uint32_t *)img->mem;
    int x, y; 
    for (x = 0; x < img->width; ++x) {
        for (y = 0; y < pos; ++y) 
            ptr[x + y * img->width] = 0xff0000;
        for (y = pos; y < pos + (img->height / 2) && y < img->height; ++y) 
            ptr[x + y * img->width] = 0x00ff;
        for (y = pos + img->height / 2 ; y < img->height; ++y)
            ptr[x + y * img->width] = 0xff0000;
    }

    g_idle_add((GSourceFunc)queue_draw, NULL);
    if (++pos >= img->height)
        pos = 0;

    return TRUE;
}


int main(int argc, char *argv[])
{
    gtk_init(&argc, &argv);

    GtkWidget *w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    dest = gtk_drawing_area_new();
    gtk_container_add(GTK_CONTAINER(w), dest);
    gtk_widget_set_usize(dest, 352, 288);
    g_signal_connect(dest, "expose-event", on_expose, NULL);
    gtk_widget_set_app_paintable(w, TRUE);
    gtk_widget_set_double_buffered(w, FALSE);
    gtk_widget_show_all(w);
    last_update = get_timer();
    double secs = get_timer();
    img =  gdk_image_new(GDK_IMAGE_FASTEST, gdk_visual_get_system(), 352, 288);
    gc = gdk_gc_new(w->window);
    
    g_signal_connect(w, "delete-event", (GCallback)gtk_main_quit, NULL);
    g_timeout_add(40, (GSourceFunc)draw_func, NULL);
    gtk_main();
    secs = get_timer() - secs;

    g_object_unref(gc);
    g_object_unref(img);
    
    g_printf("%d frames in %f seconds, %f fps\n", frames, secs, (double)frames / secs);
}
