/** * Compiled with: * gcc -o scaling scaling.c `pkg-config --cflags --libs gtk+-2.0` -std=c99 * * Logg: * * Original speed = 62.08 ms * * DST_SIZE=1000, spc-case=+mask-affine-norotcase-nomod = 54.25 ms * DST_SIZE=1000, spc-case=+mask+affine-norotcase-nomod = 51.81 ms * DST_SIZE=1000, spc-case=+mask+affine+norotcase-nomod = 36.02 ms * DST_SIZE=1000, spc-case=+mask+affine+norotcase+nomod = 31.88 ms * * The last (probably) optimization possible, is to replace this call: * * *(buffer + i) = fetch ((pixman_image_t *) pict, * bits_ofs, * x, * pict->indexed); * * with this: * * *(buffer + i) = *(bits_ofs + x); * * This reduces the time to 26.11 ms. **/ #include #include #include #define N_LOOPS 100 #define PAT_SIZE 16 #define SRC_SIZE 64 #define DST_SIZE 1000 static cairo_pattern_t *checkerboard = NULL; static cairo_pattern_t *src_pattern = NULL; static void do_composite_checker (cairo_t *cr, int width, int height) { /* Compute zoom so that the src_pattern covers the whole output image. */ double xscale = (double) width / (double) SRC_SIZE; double yscale = (double) height / (double) SRC_SIZE; cairo_identity_matrix (cr); /* Fill the surface with our background. */ cairo_set_source (cr, checkerboard); cairo_paint (cr); /* Draw the scaled image on top. */ cairo_scale (cr, xscale, yscale); cairo_set_source (cr, src_pattern); cairo_paint (cr); } int main (int argc, char *argv[]) { cairo_surface_t *image; /* Create the output context. */ cairo_surface_t *output = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, DST_SIZE, DST_SIZE); cairo_t *cr = cairo_create (output); /* Create the checker pattern. We don't actually need to draw anything on it since that wouldn't affect performance. */ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, PAT_SIZE, PAT_SIZE); checkerboard = cairo_pattern_create_for_surface (image); cairo_pattern_set_filter (checkerboard, CAIRO_FILTER_NEAREST); cairo_pattern_set_extend (checkerboard, CAIRO_EXTEND_REPEAT); /* Create the image source pattern. Again we use the NEAREST filtering which should be fastest. particle2.png is a 64x64 RGBA PNG image. You get the same timings by using cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 64, 64), but the output image won't be nice. */ image = cairo_image_surface_create_from_png ("particle2.png"); src_pattern = cairo_pattern_create_for_surface (image); cairo_pattern_set_filter (src_pattern, CAIRO_FILTER_NEAREST); cairo_pattern_set_extend (src_pattern, CAIRO_EXTEND_REPEAT); struct timeval tv_start; gettimeofday (&tv_start, NULL); for (int n = 0; n < N_LOOPS; n++) { do_composite_checker (cr, DST_SIZE, DST_SIZE); } struct timeval tv_end; gettimeofday (&tv_end, NULL); cairo_surface_write_to_png (output, "cairo-output.png"); double tv_elapsed = ((tv_end.tv_sec - tv_start.tv_sec) * 1000000.0 + (tv_end.tv_usec - tv_start.tv_usec)); double usec_p_loop = tv_elapsed / (double) N_LOOPS; printf ("%.2f ms per loop, %d loops\n", usec_p_loop / 1000.0, N_LOOPS); /* Cleanup */ cairo_pattern_destroy (checkerboard); cairo_pattern_destroy (src_pattern); cairo_destroy (cr); }