From db23ee58292d5b97223e658f0e3e4c6eb00f5453 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Fri, 11 Sep 2020 18:31:07 -0300 Subject: [PATCH] cogl/matrix: Move inverse calculation to cogl-graphene.c This special precision-bearing calculation will be used in other places, so better share them all here. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1439 --- clutter/clutter/clutter-actor.c | 3 +- clutter/clutter/clutter-stage.c | 4 +-- cogl/cogl/cogl-graphene.c | 35 +++++++++++++++++++++ cogl/cogl/cogl-graphene.h | 15 +++++++++ cogl/cogl/cogl-matrix-stack.c | 5 +-- cogl/cogl/cogl-matrix.c | 55 --------------------------------- cogl/cogl/cogl-matrix.h | 18 ----------- 7 files changed, 57 insertions(+), 78 deletions(-) diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 0a873c469..71bf95fe9 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -3166,7 +3166,8 @@ ensure_valid_actor_transform (ClutterActor *actor) CLUTTER_ACTOR_GET_CLASS (actor)->apply_transform (actor, &priv->transform); priv->has_inverse_transform = - cogl_matrix_get_inverse (&priv->transform, &priv->inverse_transform); + cogl_graphene_matrix_get_inverse (&priv->transform, + &priv->inverse_transform); priv->transform_valid = TRUE; } diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 66a94db86..cc1a64904 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -2070,8 +2070,8 @@ clutter_stage_set_perspective (ClutterStage *stage, priv->perspective.aspect, priv->perspective.z_near, priv->perspective.z_far); - cogl_matrix_get_inverse (&priv->projection, - &priv->inverse_projection); + cogl_graphene_matrix_get_inverse (&priv->projection, + &priv->inverse_projection); _clutter_stage_dirty_projection (stage); clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); diff --git a/cogl/cogl/cogl-graphene.c b/cogl/cogl/cogl-graphene.c index d9bd3bd42..90e1f5b86 100644 --- a/cogl/cogl/cogl-graphene.c +++ b/cogl/cogl/cogl-graphene.c @@ -274,3 +274,38 @@ cogl_graphene_matrix_project_points (const graphene_matrix_t *matrix, n_points); } } + +gboolean +cogl_graphene_matrix_get_inverse (const graphene_matrix_t *matrix, + graphene_matrix_t *inverse) +{ + graphene_matrix_t scaled; + graphene_matrix_t m; + gboolean invertible; + float pivot = G_MAXFLOAT; + float v[16]; + float scale; + + graphene_matrix_init_from_matrix (&m, matrix); + graphene_matrix_to_float (&m, v); + + pivot = MIN (pivot, v[0]); + pivot = MIN (pivot, v[5]); + pivot = MIN (pivot, v[10]); + pivot = MIN (pivot, v[15]); + scale = 1.f / pivot; + + graphene_matrix_init_scale (&scaled, scale, scale, scale); + + /* Float precision is a limiting factor */ + graphene_matrix_multiply (&m, &scaled, &m); + + invertible = graphene_matrix_inverse (&m, inverse); + + if (invertible) + graphene_matrix_multiply (&scaled, inverse, inverse); + else + graphene_matrix_init_identity (inverse); + + return invertible; +} diff --git a/cogl/cogl/cogl-graphene.h b/cogl/cogl/cogl-graphene.h index 67ffd8547..4a561f6d8 100644 --- a/cogl/cogl/cogl-graphene.h +++ b/cogl/cogl/cogl-graphene.h @@ -163,6 +163,21 @@ cogl_graphene_matrix_project_points (const graphene_matrix_t *matrix, void *points_out, int n_points); +/** + * cogl_graphene_matrix_get_inverse: + * @matrix: A 4x4 transformation matrix + * @inverse: (out): The destination for a 4x4 inverse transformation matrix + * + * Gets the inverse transform of a given matrix and uses it to initialize + * a new #graphene_matrix_t. + * + * Return value: %TRUE if the inverse was successfully calculated or %FALSE + * for degenerate transformations that can't be inverted (in this case the + * @inverse matrix will simply be initialized with the identity matrix) + */ +COGL_EXPORT gboolean +cogl_graphene_matrix_get_inverse (const graphene_matrix_t *matrix, + graphene_matrix_t *inverse); G_END_DECLS diff --git a/cogl/cogl/cogl-matrix-stack.c b/cogl/cogl/cogl-matrix-stack.c index a4a2d77f4..043172737 100644 --- a/cogl/cogl/cogl-matrix-stack.c +++ b/cogl/cogl/cogl-matrix-stack.c @@ -34,6 +34,7 @@ #include "cogl-config.h" #include "cogl-context-private.h" +#include "cogl-graphene.h" #include "cogl-matrix-stack.h" #include "cogl-framebuffer-private.h" #include "cogl-object-private.h" @@ -411,9 +412,9 @@ cogl_matrix_stack_get_inverse (CoglMatrixStack *stack, graphene_matrix_t *internal = cogl_matrix_stack_get (stack, &matrix); if (internal) - return cogl_matrix_get_inverse (internal, inverse); + return cogl_graphene_matrix_get_inverse (internal, inverse); else - return cogl_matrix_get_inverse (&matrix, inverse); + return cogl_graphene_matrix_get_inverse (&matrix, inverse); } /* In addition to writing the stack matrix into the give @matrix diff --git a/cogl/cogl/cogl-matrix.c b/cogl/cogl/cogl-matrix.c index f00de5e58..a4a1e9636 100644 --- a/cogl/cogl/cogl-matrix.c +++ b/cogl/cogl/cogl-matrix.c @@ -67,61 +67,6 @@ cogl_debug_matrix_print (const graphene_matrix_t *matrix) _cogl_matrix_prefix_print ("", matrix); } -/* - * Compute inverse of a transformation matrix. - * - * @mat pointer to a graphene_matrix_t structure. The matrix inverse will be - * stored in the graphene_matrix_t::inv attribute. - * - * Returns: %TRUE for success, %FALSE for failure (\p singular matrix). - * - * Calls the matrix inversion function in inv_mat_tab corresponding to the - * given matrix type. In case of failure, updates the MAT_FLAG_SINGULAR flag, - * and copies the identity matrix into graphene_matrix_t::inv. - */ - -static inline gboolean -calculate_inverse (const graphene_matrix_t *matrix, - graphene_matrix_t *inverse) -{ - graphene_matrix_t scaled; - graphene_matrix_t m; - gboolean invertible; - float pivot = G_MAXFLOAT; - float v[16]; - float scale; - - graphene_matrix_init_from_matrix (&m, matrix); - graphene_matrix_to_float (&m, v); - - pivot = MIN (pivot, v[0]); - pivot = MIN (pivot, v[5]); - pivot = MIN (pivot, v[10]); - pivot = MIN (pivot, v[15]); - scale = 1.f / pivot; - - graphene_matrix_init_scale (&scaled, scale, scale, scale); - - /* Float precision is a limiting factor */ - graphene_matrix_multiply (&m, &scaled, &m); - - invertible = graphene_matrix_inverse (&m, inverse); - - if (invertible) - graphene_matrix_multiply (&scaled, inverse, inverse); - else - graphene_matrix_init_identity (inverse); - - return invertible; -} - -gboolean -cogl_matrix_get_inverse (const graphene_matrix_t *matrix, - graphene_matrix_t *inverse) -{ - return calculate_inverse (matrix, inverse); -} - void cogl_matrix_rotate (graphene_matrix_t *matrix, float angle, diff --git a/cogl/cogl/cogl-matrix.h b/cogl/cogl/cogl-matrix.h index affbdf8d6..c4222a91e 100644 --- a/cogl/cogl/cogl-matrix.h +++ b/cogl/cogl/cogl-matrix.h @@ -485,24 +485,6 @@ cogl_matrix_copy (const graphene_matrix_t *matrix); COGL_EXPORT void cogl_matrix_free (graphene_matrix_t *matrix); -/** - * cogl_matrix_get_inverse: - * @matrix: A 4x4 transformation matrix - * @inverse: (out): The destination for a 4x4 inverse transformation matrix - * - * Gets the inverse transform of a given matrix and uses it to initialize - * a new #graphene_matrix_t. - * - * Return value: %TRUE if the inverse was successfully calculated or %FALSE - * for degenerate transformations that can't be inverted (in this case the - * @inverse matrix will simply be initialized with the identity matrix) - * - * Since: 1.2 - */ -COGL_EXPORT gboolean -cogl_matrix_get_inverse (const graphene_matrix_t *matrix, - graphene_matrix_t *inverse); - /** * cogl_matrix_is_identity: * @matrix: A #graphene_matrix_t