Cool. And here's the profile: http://www.o-hand.com/~jorn/pango-benchmarks/210-softfloat/cairo-floating-point.txt
Thanks, Jorn On Sat, 2006-08-19 at 10:03 +0000, Aivars Kalvans wrote: > I've made few more changes, to cover real-life situations when matrices > are identity matrices with some translation: > > cairo_matrix_translate(), _cairo_matrix_translate_inverse(): just > translate x0 and y0 and do not multiply whole matrix with identity matrix > _cairo_color_init_rgb(): do not multiply with alpha > _cairo_color_init_rgba(): did the same thing a compiler should do with > -Ox flag turned on (just in case optimization is disabled) > _cairo_gstate_glyph_path(), _cairo_gstate_show_glyphs(): since > translation is constant for all glyphs, precalculate it - that saves 2 > or 4 adds per iteration. For other cases (not identity matrices) > precalculate matrix with final transformation: saves one matrix > multiplication (4 muls and 2 adds) per iteration. I hope my math is > correct here. > > Jorn Baayen wrote: > > On Wed, 2006-08-16 at 00:19 +0000, Aivars Kalvans wrote: > > > >> Jorn Baayen wrote: > >> > >>> On Fri, 2006-08-11 at 09:42 +0100, Michael Meeks wrote: > >>> > >>> > >>>> Is the common case of that a multiplication by a unit matrix, [ ie. a > >>>> no-op ;-] that could be elided if that's detectable / propagate-able ? > >>>> [ though it seems there is no space in 'matrix' to ram an 'unsigned int > >>>> is-unit : 1' into ;-) Or is it perhaps a simple scaling [ reduce by 2x > >>>> the muls ? ]. > >>>> > >>>> > >>> I'm not so sure. Carl? > >>> > >>> > >> Matrix with values like { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 } does not > >> require any multiplication, because result is the same as input. Both > >> gstate->ctm and gstate->target->device_transform had such values when I > >> run your test program. This often seems to be true for "real" > >> applications as well (tried gedit). Sometimes x0 and y0 are not 0.0, but > >> for such cases we could add another workaround (x += x0, y+= y0). > >> > > > > Yea, I was not sure whether this was a common case. Apparently it is, > > because your patch causes __muldf3() to drop from 7.7% to 3.9% :) > > The full patched cairo profile is here: > > http://www.o-hand.com/~jorn/pango-benchmarks/210-softfloat/cairo-must-transform.txt > > > > Cool stuff. > > > > Thanks, > > > > Jorn > > > > > > > plain text document attachment (cairo-floating-point.diff) > diff --git a/src/cairo-color.c b/src/cairo-color.c > index e202af2..ff56fc2 100644 > --- a/src/cairo-color.c > +++ b/src/cairo-color.c > @@ -82,26 +82,35 @@ _cairo_color_init (cairo_color_t *color) > *color = cairo_color_white; > } > > -void > -_cairo_color_init_rgb (cairo_color_t *color, > - double red, double green, double blue) > -{ > - _cairo_color_init_rgba (color, red, green, blue, 1.0); > -} > - > /* We multiply colors by (0x10000 - epsilon), such that we get a uniform > * range even for 0xffff. In other words, (1.0 - epsilon) would convert > * to 0xffff, not 0xfffe. > */ > #define CAIRO_COLOR_ONE_MINUS_EPSILON (65536.0 - 1e-5) > > +void > +_cairo_color_init_rgb (cairo_color_t *color, > + double red, double green, double blue) > +{ > + color->red = red; > + color->green = green; > + color->blue = blue; > + color->alpha = 1.0; > + > + color->red_short = color->red * CAIRO_COLOR_ONE_MINUS_EPSILON; > + color->green_short = color->green * CAIRO_COLOR_ONE_MINUS_EPSILON; > + color->blue_short = color->blue * CAIRO_COLOR_ONE_MINUS_EPSILON; > + color->alpha_short = 0xffff; > +} > + > static void > _cairo_color_compute_shorts (cairo_color_t *color) > { > - color->red_short = color->red * color->alpha * > CAIRO_COLOR_ONE_MINUS_EPSILON; > - color->green_short = color->green * color->alpha * > CAIRO_COLOR_ONE_MINUS_EPSILON; > - color->blue_short = color->blue * color->alpha * > CAIRO_COLOR_ONE_MINUS_EPSILON; > - color->alpha_short = color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON; > + double alpha = color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON; > + color->red_short = color->red * alpha; > + color->green_short = color->green * alpha; > + color->blue_short = color->blue * alpha; > + color->alpha_short = alpha; > } > > void > diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c > index 2f9079b..4ed2cf3 100644 > --- a/src/cairo-gstate.c > +++ b/src/cairo-gstate.c > @@ -564,15 +564,11 @@ _cairo_gstate_get_matrix (cairo_gstate_t > cairo_status_t > _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty) > { > - cairo_matrix_t tmp; > - > _cairo_gstate_unset_scaled_font (gstate); > > - cairo_matrix_init_translate (&tmp, tx, ty); > - cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); > + cairo_matrix_translate (&gstate->ctm, tx, ty); > > - cairo_matrix_init_translate (&tmp, -tx, -ty); > - cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); > + _cairo_matrix_translate_inverse (&gstate->ctm_inverse, -tx, -ty); > > return CAIRO_STATUS_SUCCESS; > } > @@ -1417,6 +1413,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_ > cairo_status_t status; > cairo_pattern_union_t source_pattern; > cairo_glyph_t *transformed_glyphs; > + cairo_matrix_t transformation; > + cairo_bool_t ctm_is_identity, device_is_identity; > + double tx, ty; > int i; > > if (gstate->source->status) > @@ -1434,14 +1433,40 @@ _cairo_gstate_show_glyphs (cairo_gstate_ > if (transformed_glyphs == NULL) > return CAIRO_STATUS_NO_MEMORY; > > - for (i = 0; i < num_glyphs; ++i) > + ctm_is_identity = _cairo_matrix_is_identity (&gstate->ctm); > + device_is_identity = _cairo_matrix_is_identity > (&gstate->target->device_transform); > + > + tx = gstate->font_matrix.x0; > + ty = gstate->font_matrix.y0; > + > + if (ctm_is_identity && device_is_identity) > + { > + tx += gstate->ctm.x0 + gstate->target->device_transform.x0; > + ty += gstate->ctm.y0 + gstate->target->device_transform.y0; > + for (i = 0; i < num_glyphs; ++i) > + { > + transformed_glyphs[i] = glyphs[i]; > + transformed_glyphs[i].x += tx; > + transformed_glyphs[i].y += ty; > + } > + } > + else > { > - transformed_glyphs[i].index = glyphs[i].index; > - transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0; > - transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0; > - _cairo_gstate_user_to_backend (gstate, > - &transformed_glyphs[i].x, > - &transformed_glyphs[i].y); > + cairo_matrix_multiply (&transformation, > + &gstate->ctm, > + &gstate->target->device_transform); > + > + cairo_matrix_transform_point (&transformation, &tx, &ty); > + > + for (i = 0; i < num_glyphs; ++i) > + { > + transformed_glyphs[i] = glyphs[i]; > + cairo_matrix_transform_distance (&transformation, > + &transformed_glyphs[i].x, > + &transformed_glyphs[i].y); > + transformed_glyphs[i].x += tx; > + transformed_glyphs[i].y += ty; > + } > } > > _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); > @@ -1468,6 +1493,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t > cairo_status_t status; > int i; > cairo_glyph_t *transformed_glyphs = NULL; > + cairo_matrix_t transformation; > + cairo_bool_t ctm_is_identity, device_is_identity; > + double tx, ty; > > status = _cairo_gstate_ensure_scaled_font (gstate); > if (status) > @@ -1477,14 +1505,40 @@ _cairo_gstate_glyph_path (cairo_gstate_t > if (transformed_glyphs == NULL) > return CAIRO_STATUS_NO_MEMORY; > > - for (i = 0; i < num_glyphs; ++i) > + ctm_is_identity = _cairo_matrix_is_identity (&gstate->ctm); > + device_is_identity = _cairo_matrix_is_identity > (&gstate->target->device_transform); > + > + tx = gstate->font_matrix.x0; > + ty = gstate->font_matrix.y0; > + > + if (ctm_is_identity && device_is_identity) > + { > + tx += gstate->ctm.x0 + gstate->target->device_transform.x0; > + ty += gstate->ctm.y0 + gstate->target->device_transform.y0; > + for (i = 0; i < num_glyphs; ++i) > + { > + transformed_glyphs[i] = glyphs[i]; > + transformed_glyphs[i].x += tx; > + transformed_glyphs[i].y += ty; > + } > + } > + else > { > - transformed_glyphs[i].index = glyphs[i].index; > - transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0; > - transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0; > - _cairo_gstate_user_to_backend (gstate, > - &(transformed_glyphs[i].x), > - &(transformed_glyphs[i].y)); > + cairo_matrix_multiply (&transformation, > + &gstate->ctm, > + &gstate->target->device_transform); > + > + cairo_matrix_transform_point (&transformation, &tx, &ty); > + > + for (i = 0; i < num_glyphs; ++i) > + { > + transformed_glyphs[i] = glyphs[i]; > + cairo_matrix_transform_distance (&transformation, > + &transformed_glyphs[i].x, > + &transformed_glyphs[i].y); > + transformed_glyphs[i].x += tx; > + transformed_glyphs[i].y += ty; > + } > } > > status = _cairo_scaled_font_glyph_path (gstate->scaled_font, > diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c > index e418ef3..7723209 100644 > --- a/src/cairo-matrix.c > +++ b/src/cairo-matrix.c > @@ -164,11 +164,15 @@ slim_hidden_def(cairo_matrix_init_transl > void > cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty) > { > - cairo_matrix_t tmp; > - > - cairo_matrix_init_translate (&tmp, tx, ty); > + matrix->x0 += tx * matrix->xx + ty * matrix->xy; > + matrix->y0 += tx * matrix->yx + ty * matrix->yy; > +} > > - cairo_matrix_multiply (matrix, &tmp, matrix); > +void > +_cairo_matrix_translate_inverse (cairo_matrix_t *matrix, double tx, double > ty) > +{ > + matrix->x0 += tx; > + matrix->y0 += ty; > } > > /** > @@ -529,11 +533,28 @@ _cairo_matrix_compute_scale_factors (con > } > > cairo_bool_t > +_cairo_matrix_has_transform (const cairo_matrix_t *matrix) > +{ > + return (matrix->xx != 1.0 || matrix->yx != 0.0 || > + matrix->xy != 0.0 || matrix->yy != 1.0 || > + matrix->x0 != 0.0 || matrix->y0 != 0.0); > +} > + > +cairo_bool_t > _cairo_matrix_is_identity (const cairo_matrix_t *matrix) > { > +#if defined (__arm__) > + /* memcmp() should be faster for soft float */ > + static cairo_matrix_t identity = { > + 1.0, 0.0, > + 0.0, 1.0, > + 0.0, 0.0 > + }; > + return (memcmp (matrix, &identity, 4 * sizeof(double)) == 0); > +#else > return (matrix->xx == 1.0 && matrix->yx == 0.0 && > - matrix->xy == 0.0 && matrix->yy == 1.0 && > - matrix->x0 == 0.0 && matrix->y0 == 0.0); > + matrix->xy == 0.0 && matrix->yy == 1.0); > +#endif > } > > cairo_bool_t > diff --git a/src/cairo-surface.c b/src/cairo-surface.c > index 0468ca2..40e31a7 100644 > --- a/src/cairo-surface.c > +++ b/src/cairo-surface.c > @@ -853,7 +853,7 @@ cairo_surface_set_fallback_resolution (c > cairo_bool_t > _cairo_surface_has_device_transform (cairo_surface_t *surface) > { > - return ! _cairo_matrix_is_identity (&surface->device_transform); > + return _cairo_matrix_has_transform (&surface->device_transform); > } > > /** > diff --git a/src/cairoint.h b/src/cairoint.h > index 13d19b1..81963a0 100644 > --- a/src/cairoint.h > +++ b/src/cairoint.h > @@ -2141,6 +2141,12 @@ cairo_private void > _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, > pixman_transform_t *pixman_transform); > > +cairo_private cairo_bool_t > +_cairo_matrix_has_transform (const cairo_matrix_t *matrix); > + > +cairo_private void > +_cairo_matrix_translate_inverse (cairo_matrix_t *matrix, double tx, double > ty); > + > /* cairo_traps.c */ > cairo_private void > _cairo_traps_init (cairo_traps_t *traps); > -- OpenedHand Ltd. http://o-hand.com/ _______________________________________________ Performance-list mailing list Performance-list@gnome.org http://mail.gnome.org/mailman/listinfo/performance-list