From 9130dc1311b0d9b1500347a625691e37f6a211fe Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 8 Feb 2011 10:37:15 +0000 Subject: [PATCH] util: optimize _clutter_util_fully_transform_vertices Instead of unconditionally combining the modelview and projection matrices and then iterating each of the vertices to call cogl_matrix_transform_point for each one in turn we now only combine the matrices if there are more than 4 vertices (with less than 4 vertices its less work to transform them separately) and we use the new cogl_vertex_{transform,project}_points APIs which can hopefully vectorize the transformations. Finally the perspective divide and viewport scale is done in a separate loop at the end and we don't do the spurious perspective divide and viewport scale for the z component. --- clutter/clutter-util.c | 66 ++++++++++++++++++++++++--------- clutter/cogl/cogl/cogl-matrix.c | 14 +++---- clutter/cogl/cogl/cogl-matrix.h | 4 +- 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/clutter/clutter-util.c b/clutter/clutter-util.c index a45d00fac..9793f7dca 100644 --- a/clutter/clutter-util.c +++ b/clutter/clutter-util.c @@ -81,6 +81,14 @@ _clutter_gettext (const gchar *str) #define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) #define MTX_GL_SCALE_Z(z,w,v1,v2) (MTX_GL_SCALE_X ((z), (w), (v1), (v2))) +typedef struct _ClutterVertex4 +{ + float x; + float y; + float z; + float w; +} ClutterVertex4; + void _clutter_util_fully_transform_vertices (const CoglMatrix *modelview, const CoglMatrix *projection, @@ -90,31 +98,53 @@ _clutter_util_fully_transform_vertices (const CoglMatrix *modelview, int n_vertices) { CoglMatrix modelview_projection; + ClutterVertex4 *vertices_tmp; int i; - /* XXX: we should find a way to cache this per actor */ - cogl_matrix_multiply (&modelview_projection, - projection, - modelview); + vertices_tmp = g_alloca (sizeof (ClutterVertex4) * n_vertices); + + if (n_vertices >= 4) + { + /* XXX: we should find a way to cache this per actor */ + cogl_matrix_multiply (&modelview_projection, + projection, + modelview); + cogl_matrix_project_points (&modelview_projection, + 3, + sizeof (ClutterVertex), + vertices_in, + sizeof (ClutterVertex4), + vertices_tmp, + n_vertices); + } + else + { + cogl_matrix_transform_points (modelview, + 3, + sizeof (ClutterVertex), + vertices_in, + sizeof (ClutterVertex4), + vertices_tmp, + n_vertices); + + cogl_matrix_project_points (projection, + 3, + sizeof (ClutterVertex4), + vertices_tmp, + sizeof (ClutterVertex4), + vertices_tmp, + n_vertices); + } for (i = 0; i < n_vertices; i++) { - const ClutterVertex *vertex_in = &vertices_in[i]; + ClutterVertex4 vertex_tmp = vertices_tmp[i]; ClutterVertex *vertex_out = &vertices_out[i]; - gfloat x, y, z, w; - - x = vertex_in->x; - y = vertex_in->y; - z = vertex_in->z; - w = 1.0; - - /* Transform the point using the modelview matrix */ - cogl_matrix_transform_point (&modelview_projection, &x, &y, &z, &w); - /* Finally translate from OpenGL coords to window coords */ - vertex_out->x = MTX_GL_SCALE_X (x, w, viewport[2], viewport[0]); - vertex_out->y = MTX_GL_SCALE_Y (y, w, viewport[3], viewport[1]); - vertex_out->z = MTX_GL_SCALE_Z (z, w, viewport[2], viewport[0]); + vertex_out->x = MTX_GL_SCALE_X (vertex_tmp.x, vertex_tmp.w, + viewport[2], viewport[0]); + vertex_out->y = MTX_GL_SCALE_Y (vertex_tmp.y, vertex_tmp.w, + viewport[3], viewport[1]); } } diff --git a/clutter/cogl/cogl/cogl-matrix.c b/clutter/cogl/cogl/cogl-matrix.c index 344b67d5b..625b89f68 100644 --- a/clutter/cogl/cogl/cogl-matrix.c +++ b/clutter/cogl/cogl/cogl-matrix.c @@ -498,7 +498,7 @@ typedef struct _Point4f static void _cogl_matrix_transform_points_f2 (const CoglMatrix *matrix, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points) @@ -519,7 +519,7 @@ _cogl_matrix_transform_points_f2 (const CoglMatrix *matrix, static void _cogl_matrix_project_points_f2 (const CoglMatrix *matrix, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points) @@ -541,7 +541,7 @@ _cogl_matrix_project_points_f2 (const CoglMatrix *matrix, static void _cogl_matrix_transform_points_f3 (const CoglMatrix *matrix, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points) @@ -565,7 +565,7 @@ _cogl_matrix_transform_points_f3 (const CoglMatrix *matrix, static void _cogl_matrix_project_points_f3 (const CoglMatrix *matrix, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points) @@ -591,7 +591,7 @@ _cogl_matrix_project_points_f3 (const CoglMatrix *matrix, static void _cogl_matrix_project_points_f4 (const CoglMatrix *matrix, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points) @@ -618,7 +618,7 @@ void cogl_matrix_transform_points (const CoglMatrix *matrix, int n_components, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points) @@ -646,7 +646,7 @@ void cogl_matrix_project_points (const CoglMatrix *matrix, int n_components, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points) diff --git a/clutter/cogl/cogl/cogl-matrix.h b/clutter/cogl/cogl/cogl-matrix.h index c5d59871d..1db1d8fa5 100644 --- a/clutter/cogl/cogl/cogl-matrix.h +++ b/clutter/cogl/cogl/cogl-matrix.h @@ -505,7 +505,7 @@ void cogl_matrix_transform_points (const CoglMatrix *matrix, int n_components, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points); @@ -560,7 +560,7 @@ void cogl_matrix_project_points (const CoglMatrix *matrix, int n_components, size_t stride_in, - void *points_in, + const void *points_in, size_t stride_out, void *points_out, int n_points);