/* * gtkDPS time test program by hideki * */ #include #include #include #include #include #include #include #include #include "gtkDPS.h" #define DEFAULT_TEST_TIMES 20 gint test_times = DEFAULT_TEST_TIMES; gboolean with_alpha_blending = FALSE; #define WIDTH 400 #define HEIGHT 240 #define CELL_SIZE 40 #define CIRCLE_STEP 1 #define CENTER_X 50 #define CENTER_Y 50 static void init (GtkWidget *widget); static void do_test (GtkWidget *widget, gpointer data); static double draw_test (GtkWidget *widget, int test_num); static void draw_background_cells(GtkDPSArea * area, gfloat dps_width, gfloat dps_height); static void draw_cell(DPSContext ctxt, float x, float y, float width, float height); static void draw_background_circles(GtkDPSArea * area, gfloat dps_width, gfloat dps_height); static void draw_circle(DPSContext ctxt, int radius, int max_radius); static void draw_background_triangle(GtkDPSArea * area, gfloat dps_width, gfloat dps_height); static void record_start(void); static double record_end(void); static void dialog_close_callback (GtkWidget *widget, gpointer data); struct background_drawer { void (* func) (GtkDPSArea * area, gfloat dps_width, gfloat dps_height); gchar * name; }; struct background_drawer background_drawer[] = { {draw_background_cells, "Cells"}, {draw_background_circles, "Circles"}, {draw_background_triangle, "Triangle"} /* Add by your own! */ /* GModule ? */ }; const gint n_background_drawer = sizeof(background_drawer)/sizeof(struct background_drawer); /* * main function */ int main(int argc, char **argv) { GtkWidget *DPS_area; GtkWidget *dialog; GtkWidget * vbox; GtkWidget *exit_button; GtkWidget *test_button; gint i; gboolean with_shared_context = FALSE; gfloat dps_width, dps_height; for (i = 1; i < argc; i++) { if (0 == strcmp(argv[i], "--help")) { const gchar * version = gtk_dps_version(); fprintf(stderr, "Usage: dpsmark [OPTIONS] [TEST_TIMES]\n" "Simple DPS bench mark program. " "dpsmark is part of gtkDPS version %s\n" "\n" " --help: print this help\n" " --with-alpha-blending: Use transparent rectangle\n" " --with-shared-context: enable shared context\n" " DGS has to handle two contexts.\n" " --version: print version\n" "By default the test is run 20 times.\n", version); return 0; } else if (0 == strcmp(argv[i], "--version")) { const gchar * version = gtk_dps_version(); fprintf(stderr, "GtkDPS %s\n", version); return 0; } else if (0 == strcmp(argv[i], "--with-shared-context")) with_shared_context = TRUE; else if (0 == strcmp(argv[i], "--with-alpha-blending")) with_alpha_blending = TRUE; else if (0 != atoi(argv[i])) { gint tmp; tmp = atoi(argv[i]); if (tmp > 0) test_times = tmp; } } gtk_init(&argc, &argv); gtk_dps_init(&argc, &argv); if (with_shared_context) (void)gdk_dps_context_get_shared(); /* create a new dialog */ dialog = gtk_dialog_new(); vbox = GTK_DIALOG(dialog)->vbox; /* create a new dps area 1: Cache 2: Cell background 3: Gradation background ... */ DPS_area = gtk_dps_area_new(n_background_drawer+1); /* set the area size */ gtk_dps_area_size(GTK_DPS_AREA(DPS_area), WIDTH, HEIGHT); /* This packs the button into the dialog. */ gtk_box_pack_start(GTK_BOX(vbox), DPS_area, FALSE, FALSE, 0); /* display DPS_area */ gtk_widget_show(DPS_area); /* create a new button with the label "Test". */ test_button = gtk_button_new_with_label("Test"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), test_button, TRUE, TRUE, 0); gtk_signal_connect_object(GTK_OBJECT(test_button), "clicked", (GtkSignalFunc)do_test, GTK_OBJECT(DPS_area)); gtk_widget_show(test_button); /* create a new button with the label "Exit". */ exit_button = gtk_button_new_with_label("Exit"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), exit_button, TRUE, TRUE, 0); gtk_signal_connect(GTK_OBJECT(exit_button), "clicked", (GtkSignalFunc)dialog_close_callback, NULL); gtk_widget_show(exit_button); /* display the dialog */ gtk_widget_show(dialog); /* re-calculate area size */ dps_width = gtk_dps_area_coordtr_width(GTK_DPS_AREA(DPS_area), GDK_DPS_TRDIR_X2DPS, (gfloat)WIDTH); dps_height = gtk_dps_area_coordtr_height(GTK_DPS_AREA(DPS_area), GDK_DPS_TRDIR_X2DPS, (gfloat)HEIGHT); dps_width = WIDTH*WIDTH/dps_width; dps_height = HEIGHT*HEIGHT/dps_height; gtk_dps_area_size(GTK_DPS_AREA(DPS_area), (int)dps_width, (int)dps_height); gtk_main(); return 0; } static void init (GtkWidget *widget) { gdouble time; gint i; gfloat dps_width, dps_height; gtk_dps_area_get_size(GTK_DPS_AREA(widget), &dps_width, &dps_height); for (i = 0; i < n_background_drawer; i++) { fprintf(stderr, "Building background: %s...", background_drawer[i].name); gtk_dps_widget_begin(widget); DPSerasepage(raw_ctxt); gtk_dps_widget_end(); record_start(); background_drawer[i].func(GTK_DPS_AREA (widget), dps_width, dps_height); time = record_end(); gtk_dps_area_map_pixmap(GTK_DPS_AREA (widget), i+1, 0, GDK_DPS_WORLD_X, NULL); fprintf(stderr, "done(%f)\n", time); } } static void do_test (GtkWidget *widget, gpointer data) { int i; double result=0; double average=0; init(widget); sleep(1); for (i=0; i< test_times; i++) { result = draw_test(widget, i); fprintf(stderr,"%2d time: %f\n",i+1,result); average += result; } fprintf(stderr,"average time of %d: %f\n", test_times, average/test_times); } static double draw_test (GtkWidget *widget, int test_num) { int i; double result; float bar_width = 10.0; int src_pixmap = test_num % n_background_drawer + 1; gfloat dps_width, dps_height; GdkDPSRectangle *dps_rect; GdkDPSRectangle *bar_rect; GdkDPSRectangle *copy_rect; gtk_dps_area_get_size(GTK_DPS_AREA(widget), &dps_width, &dps_height); gtk_dps_area_map_pixmap(GTK_DPS_AREA (widget), GTK_DPS_AREA_PIXMAP, src_pixmap, GDK_DPS_WORLD_X, NULL); gtk_dps_area_map_area_on_screen(GTK_DPS_AREA (widget), NULL); dps_rect = gdk_dps_rectangle_new(0.0, 0.0, bar_width, dps_height); bar_rect = gdk_dps_rectangle_new(0.0, 0.0, bar_width, dps_height); copy_rect = gdk_dps_rectangle_new(0.0, 0.0, bar_width, dps_height); gtk_dps_widget_begin(widget); { DPSnewpath(raw_ctxt); DPSsetrgbcolor(raw_ctxt, 1.0, 0.0, 0.0); if (with_alpha_blending) DPSPrintf(raw_ctxt, "0.8 setalpha"); } gtk_dps_widget_end(); record_start(); for (i = 0 ; i <= (int)dps_width+1; i++) { dps_rect->x = i-1; gtk_dps_area_map_pixmap(GTK_DPS_AREA (widget), GTK_DPS_AREA_PIXMAP, src_pixmap, GDK_DPS_WORLD_DPS, dps_rect); bar_rect->x = i; gtk_dps_widget_begin(widget); if (with_alpha_blending) DPSPrintf(raw_ctxt, "%f %f %f %f 2 compositerect", bar_rect->x, bar_rect->y, bar_rect->width, bar_rect->height); else DPSrectfill(raw_ctxt, bar_rect->x, bar_rect->y, bar_rect->width, bar_rect->height); gtk_dps_widget_end(); gdk_dps_rectangle_union(dps_rect, bar_rect, copy_rect); gdk_dps_rectangle_integral(copy_rect); gtk_dps_area_map_pixmap(GTK_DPS_AREA (widget), GTK_DPS_SCREEN, GTK_DPS_AREA_PIXMAP, GDK_DPS_WORLD_DPS, copy_rect); } result = record_end(); gdk_dps_rectangle_free(copy_rect); gdk_dps_rectangle_free(bar_rect); gdk_dps_rectangle_free(dps_rect); gtk_dps_widget_begin(widget); if (with_alpha_blending) DPSPrintf(raw_ctxt, "1.0 setalpha"); gtk_dps_widget_end(); return result; } /* * Drawing background */ static void draw_cell(DPSContext ctxt, float x, float y, float width, float height) { int k; float l; float r, g, b; int cx = x + (width/2), cy = y + (height/2); r = (float)(random()%256)/255.0; g = (float)(random()%256)/255.0; b = (float)(random()%256)/255.0; for (k = width/2; k > 0; k--) { l = 1.0 + (float)k/5.0; DPSsetrgbcolor(ctxt, r/l, g/l, b/l); DPSrectfill(ctxt, cx-k,cy-k, 2*k, 2*k); } DPSsetrgbcolor(ctxt, 0.0, 0.0, 0.0); DPSrectstroke(ctxt, x,y,width, height); } static void draw_background_cells(GtkDPSArea * area, gfloat dps_width, gfloat dps_height) { int i, j; const int cell_size = CELL_SIZE; gtk_dps_widget_begin(area); { DPSnewpath(raw_ctxt); DPSsetrgbcolor(raw_ctxt, 1.0, 1.0, 1.0); DPSrectfill(raw_ctxt,0,0,dps_width, dps_height); for (i = 0; i < (int)dps_width; i += cell_size) for (j = 0; j < (int)dps_height; j += cell_size) draw_cell(raw_ctxt, i, j, cell_size, cell_size); } gtk_dps_widget_end(); } static void draw_background_circles(GtkDPSArea * area, gfloat dps_width, gfloat dps_height) { int max_radius, i; const int citcle_step = CIRCLE_STEP; gtk_dps_widget_begin(area); { DPSnewpath(raw_ctxt); DPSsetrgbcolor(raw_ctxt, 1.0, 1.0, 1.0); DPSrectfill(raw_ctxt,0,0, dps_width, dps_height); max_radius = MAX(dps_width, dps_height); for (i = max_radius; i > 0; i -= citcle_step) draw_circle(raw_ctxt, i, max_radius); } gtk_dps_widget_end(); } static void draw_circle(DPSContext ctxt, int radius, int max_radius) { DPSsetrgbcolor(ctxt, 0.8*(1.0 - (float)radius/(float)max_radius), 0.0, (float)radius/(float)max_radius); DPSarc(ctxt, (float)CENTER_X, (float)CENTER_Y, (float)radius, 0.0, 360.0); DPSfill(ctxt); } static void draw_background_triangle(GtkDPSArea * area, gfloat dps_width, gfloat dps_height) { gtk_dps_widget_begin(area); { DPSsetrgbcolor(raw_ctxt, 0.0, 0.4, 0.0); DPSnewpath(raw_ctxt); DPSmoveto(raw_ctxt, 0.0, 0.0); DPSlineto(raw_ctxt, 100.0, 50.0); DPSlineto(raw_ctxt, 50.0, 100.0); DPSclosepath(raw_ctxt); DPSfill(raw_ctxt); } gtk_dps_widget_end(); } /* * Utility */ struct timeval old_tv; struct timezone tz; static void record_start(void) { gettimeofday(&old_tv, &tz); } static double record_end(void) { struct timeval new_tv; long sec, usec; gettimeofday(&new_tv, &tz); if (new_tv.tv_usec > old_tv.tv_usec) { sec = new_tv.tv_sec - old_tv.tv_sec; usec = new_tv.tv_usec - old_tv.tv_usec; } else { sec = new_tv.tv_sec - old_tv.tv_sec -1; usec = new_tv.tv_usec + 1000000 - old_tv.tv_usec; } return ((double)sec + ((double)usec)/1000000.0); } static void dialog_close_callback (GtkWidget *widget, gpointer data) { gtk_exit(1); }