Hi Robert, On 29 January 2010 02:06, Robert Gibbs <gibbsrc@xxxxxxxxx> wrote: > I have attached an example program. With this example I get 220 FPS using a > pixmap for buffer and 11 FPS using the GDK buffering. Here's a very slightly modified version of your program. I put the fps measure in the expose handler rather than in the idle callback, since GDK can coalesce exposes, and added a bit more feedback about when it's starting and stopping tests. On my work machine (x.org 1.6.4 with nvidia driver 185 on a quadro nvs 285, compiz enabled, 1920x1200 display) I get these results: Using GDK buffering starting fps test 1 fps 62 fps 64 fps 64 fps 64 fps 64 fps 64 fps stopping fps test Using internal buffer starting fps test 64 fps 127 fps 52 fps 53 fps 52 fps 52 fps 52 fps 53 fps 52 fps 53 fps So on this machine anyway, the gdk double buffering does not cause terrible performance. John
/* compile with gcc double-buffer.c `pkg-config gtk+-2.0 --cflags --libs` */ #include <math.h> #include <time.h> #include <string.h> #include <gtk/gtk.h> #include <gdk/gdk.h> #include <gdk/gdkkeysyms.h> typedef struct { guint idle_id; GtkWidget *da; GdkPixmap *pix; gboolean use_buffer; } AppData; static gboolean on_expose (GtkWidget * widget, GdkEventExpose * event, AppData * app) { static GTimer *timer = NULL; static int frames = 0; GdkColor color; GdkDrawable *drawable; GdkGC *gc; if (!timer) timer = g_timer_new (); frames += 1; if (g_timer_elapsed (timer, NULL) > 1) { printf ("%d fps\n", frames); g_timer_reset (timer); frames = 0; } if (app->use_buffer) { drawable = GDK_DRAWABLE (app->pix); gc = gdk_gc_new (drawable); gdk_color_parse ("black", &color); gdk_gc_set_rgb_fg_color (gc, &color); gdk_draw_rectangle (drawable, gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); } else { drawable = GDK_DRAWABLE (widget->window); gc = gdk_gc_new (drawable); } gdk_color_parse ("red", &color); gdk_gc_set_rgb_fg_color (gc, &color); gdk_draw_line (drawable, gc, 0, 0, widget->allocation.width, widget->allocation.height); gdk_draw_line (drawable, gc, widget->allocation.width, 0, 0, widget->allocation.height); if (app->use_buffer) { gdk_draw_drawable (GDK_DRAWABLE (widget->window), gc, GDK_DRAWABLE (app->pix), 0, 0, 0, 0, -1, -1); } return TRUE; } static gboolean on_configure (GtkWidget * widget, GdkEventConfigure * event, AppData * app) { if (app->use_buffer) { if (app->pix) g_object_unref (app->pix); app->pix = gdk_pixmap_new (GDK_DRAWABLE (app->da->window), event->width, event->height, -1); } return TRUE; } static gboolean on_fps_idle (AppData * app) { gtk_widget_queue_draw (app->da); return TRUE; } static gboolean on_key_press_event (GtkWidget * widget, GdkEventKey * event, AppData * app) { switch (event->keyval) { case GDK_t: case GDK_T: if (g_source_remove_by_user_data (app)) { printf ("stopping fps test\n"); } else { printf ("starting fps test\n"); g_idle_add ((GSourceFunc) on_fps_idle, app); } break; case GDK_b: case GDK_B: if (app->use_buffer) { printf ("Using GDK buffering\n"); app->use_buffer = FALSE; GTK_WIDGET_SET_FLAGS (app->da, GTK_DOUBLE_BUFFERED); if (app->pix) g_object_unref (app->pix); app->pix = NULL; } else { printf ("Using internal buffer\n"); app->use_buffer = TRUE; GTK_WIDGET_UNSET_FLAGS (app->da, GTK_DOUBLE_BUFFERED); app->pix = gdk_pixmap_new (GDK_DRAWABLE (app->da->window), app->da->allocation.width, app->da->allocation.height, -1); } break; default: break; } return FALSE; } static char *keymaps = "\ t.T\t\tStart or stop a frame per second (FPS) timing test.\n\ b.B\t\tToggle internal buffering on or off..\n\ "; int main (int argc, char **argv) { GtkWidget *window; GdkColor color; AppData app; memset (&app, 0, sizeof (app)); gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (window, "delete-event", gtk_main_quit, NULL); app.da = gtk_drawing_area_new (); GTK_WIDGET_SET_FLAGS (app.da, GTK_CAN_FOCUS); gdk_color_parse ("black", &color); gtk_widget_modify_bg (app.da, GTK_STATE_NORMAL, &color); gtk_widget_set_size_request (app.da, 400, 400); gtk_widget_set_events (app.da, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_EXPOSURE_MASK); g_signal_connect (app.da, "key-press-event", G_CALLBACK (on_key_press_event), &app); g_signal_connect (app.da, "expose-event", G_CALLBACK (on_expose), &app); g_signal_connect (app.da, "configure-event", G_CALLBACK (on_configure), &app); gtk_container_add (GTK_CONTAINER (window), app.da); gtk_widget_show_all (window); printf ("%s\n", keymaps); gtk_main (); return 0; }
_______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list