glutils: fix matrix operations everywhere
[platform/upstream/gstreamer.git] / tests / check / libs / gstglmatrix.c
1 /* GStreamer
2  *
3  * Copyright (C) 2014 Matthew Waters <ystreet00@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24
25 #include <gst/gl/gstglutils.c>
26 #undef GST_CAT_DEFAULT
27 #include <gst/check/gstcheck.h>
28
29 #define EPSILON 0.0001f
30 #define FEQ(a,b) (fabs(a-b) < EPSILON)
31
32 static void
33 debug_matrix (const float *m)
34 {
35   int i;
36   for (i = 0; i < 4; i++) {
37     GST_DEBUG ("%10.4f %10.4f %10.4f %10.4f", m[i * 4 + 0], m[i * 4 + 1],
38         m[i * 4 + 2], m[i * 4 + 3]);
39   }
40 }
41
42 GST_START_TEST (test_matrix_multiply)
43 {
44   /* A * B == C */
45   const float A[] = {
46     1., 1., 2., 5.,
47     0., 3., 0., 1.,
48     2., 0., 3., 1.,
49     3., 2., 1., 0.,
50   };
51
52   const float B[] = {
53     3., 1., 0., 2.,
54     1., 0., 3., 2.,
55     0., 1., 2., 3.,
56     3., 2., 1., 0.,
57   };
58
59   const float C[] = {
60     19., 13., 12., 10.,
61     6., 2., 10., 6.,
62     9., 7., 7., 13.,
63     11., 4., 8., 13.,
64   };
65
66   float res[16];
67   int i;
68
69   gst_gl_multiply_matrix4 (A, B, res);
70   GST_DEBUG ("result");
71   debug_matrix (res);
72
73   for (i = 0; i < G_N_ELEMENTS (res); i++) {
74     fail_unless (FEQ (res[i], C[i]), "value %f at index %u does not match "
75         "expected value %f", res[i], i, C[i]);
76   }
77 }
78
79 GST_END_TEST;
80
81 GST_START_TEST (test_matrix_ndc)
82 {
83   GstBuffer *buffer = gst_buffer_new ();
84   GstVideoAffineTransformationMeta *aff_meta;
85   float res[16];
86   int i;
87
88   const float m[] = {
89     1., 0., 0., 0.,
90     0., 1., 0., 0.,
91     0., 0., 1., 0.,
92     0., 0., 0., 1.,
93   };
94
95   const float n[] = {
96     4., 6., 4., 9.,
97     1., 5., 8., 2.,
98     9., 3., 5., 8.,
99     3., 7., 9., 1.,
100   };
101
102   aff_meta = gst_buffer_add_video_affine_transformation_meta (buffer);
103
104   /* test default identity matrix */
105   gst_gl_get_affine_transformation_meta_as_ndc (aff_meta, res);
106   GST_DEBUG ("result");
107   debug_matrix (res);
108
109   for (i = 0; i < G_N_ELEMENTS (res); i++) {
110     fail_unless (FEQ (res[i], m[i]), "value %f at index %u does not match "
111         "expected value %f", res[i], i, m[i]);
112   }
113
114   /* test setting and receiving the same values */
115   gst_gl_set_affine_transformation_meta_from_ndc (aff_meta, n);
116   gst_gl_get_affine_transformation_meta_as_ndc (aff_meta, res);
117
118   GST_DEBUG ("result");
119   debug_matrix (res);
120
121   for (i = 0; i < G_N_ELEMENTS (res); i++) {
122     fail_unless (FEQ (res[i], n[i]), "value %f at index %u does not match "
123         "expected value %f", res[i], i, n[i]);
124   }
125
126   gst_buffer_unref (buffer);
127 }
128
129 GST_END_TEST;
130 #if 0
131 static void
132 transpose_matrix4 (float *m, float *res)
133 {
134   int i, j;
135
136   for (i = 0; i < 4; i++) {
137     for (j = 0; j < 4; j++) {
138       int idx = i + (j * 4);
139       int swapped_idx = j + (i * 4);
140
141       if (i == j)
142         fail_unless (idx == swapped_idx);
143
144       res[swapped_idx] = m[idx];
145     }
146   }
147 }
148
149 static float
150 dot4 (float *v1, float *v2)
151 {
152   GST_TRACE ("%.4f * %.4f + %.4f * %.4f + %.4f * %.4f + %.4f * %.4f",
153       v1[0], v2[0], v1[1], v2[1], v1[2], v2[2], v1[3], v2[3]);
154   return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] + v1[3] * v2[3];
155 }
156
157 /* m * v */
158 static void
159 _matrix_mult_vertex4 (float *m, float *v, float *res)
160 {
161   res[0] = dot4 (&m[0], v);
162   res[1] = dot4 (&m[4], v);
163   res[2] = dot4 (&m[8], v);
164   res[3] = dot4 (&m[12], v);
165 }
166
167 /* v * m */
168 static void
169 _vertex_mult_matrix4 (float *v, float *m, float *res)
170 {
171   float tmp[16] = { 0., };
172
173   transpose_matrix4 (m, tmp);
174   _matrix_mult_vertex4 (tmp, v, res);
175 }
176
177 GST_START_TEST (test_matrix_vertex_identity)
178 {
179   float identity[] = {
180     1., 0., 0., 0.,
181     0., 1., 0., 0.,
182     0., 0., 1., 0.,
183     0., 0., 0., 1.,
184   };
185
186   float v[] = { 1., 1., 1., 1. };
187   float res[4] = { 0., };
188   int i;
189
190   _vertex_mult_matrix4 (v, identity, res);
191   GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
192   GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
193
194   for (i = 0; i < 4; i++) {
195     fail_unless (FEQ (res[i], v[i]), "value %f at index %u does not match "
196         "expected value %f", res[i], i, v[i]);
197   }
198
199   _matrix_mult_vertex4 (identity, v, res);
200   GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
201   GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
202
203   for (i = 0; i < 4; i++) {
204     fail_unless (FEQ (res[i], v[i]), "value %f at index %u does not match "
205         "expected value %f", res[i], i, v[i]);
206   }
207 }
208
209 GST_END_TEST;
210
211 GST_START_TEST (test_matrix_vertex_scale)
212 {
213   float scale[] = {
214     1.5, 0., 0., 0.,
215     0., 2.5, 0., 0.,
216     0., 0., 3., 0.,
217     0., 0., 0., 1.,
218   };
219
220   float v[] = { 1., 1., 1., 1. };
221   float expected[] = { 1.5, 2.5, 3., 1. };
222   float res[4] = { 0., };
223   int i;
224
225   _vertex_mult_matrix4 (v, scale, res);
226   GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
227   GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
228
229   for (i = 0; i < 4; i++) {
230     fail_unless (FEQ (res[i], expected[i]),
231         "value %f at index %u does not match " "expected value %f", res[i], i,
232         expected[i]);
233   }
234
235   _matrix_mult_vertex4 (scale, v, res);
236   GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
237   GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
238
239   for (i = 0; i < 4; i++) {
240     fail_unless (FEQ (res[i], expected[i]),
241         "value %f at index %u does not match " "expected value %f", res[i], i,
242         expected[i]);
243   }
244 }
245
246 GST_END_TEST;
247 #endif
248
249 static Suite *
250 gst_gl_upload_suite (void)
251 {
252   Suite *s = suite_create ("GstGLMatrix");
253   TCase *tc_chain = tcase_create ("matrix");
254
255   suite_add_tcase (s, tc_chain);
256   tcase_add_test (tc_chain, test_matrix_multiply);
257   tcase_add_test (tc_chain, test_matrix_ndc);
258
259   return s;
260 }
261
262 GST_CHECK_MAIN (gst_gl_upload);