Re: performance problems double buffering to 1600x1200 window
- From: Robert Gibbs <gibbsrc gmail com>
- To: gtk-list gnome org
- Subject: Re: performance problems double buffering to 1600x1200 window
- Date: Thu, 28 Jan 2010 21:06:23 -0500
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.
I am using the X11 backend with Compiz.
I have run it with sysprof. sysprof tells me that most of the time is being spent in the X process but there is no further detail as to where in the X11 library.
I will experiment more to see if it is related to re-allocating the pixmap.
On Wed, Jan 27, 2010 at 9:12 PM, Robert Gibbs
<gibbsrc gmail com> wrote:
I am running into a severe performance degradation when using the built in GtkDrawingArea double buffering to a 1600x1200 window. The program sets a default priority idle handler which calls gtk_widget_queue_draw. The expose event originally would draw about 1000 polygons, but I commented out the drawing portion and still saw the same poor performance. The best performance I can get is about 10 frames per second.
If call GTK_WIDGET_UNSET_FLAGS (drawing_area, GTK_DOUBLE_BUFFERED), then use my own pixmap for double buffering, the performance goes up to 50 frames per second.
Can anyone tell me why the built-in double buffering would yield such poor performance?
#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)
{
GdkColor color;
GdkDrawable *drawable;
GdkGC *gc;
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)
{
static time_t t = 0;
static float total = 0;
if (t == 0) t = time(0);
gtk_widget_queue_draw(app->da);
total++;
if (time(0) - t >= 10) {
printf("%.1f FPS\n", total / ((float)(time(0)-t)));
t = time(0);
total = 0;
}
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))
{
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;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]