wlt: fix shl_hook API changes
[platform/upstream/kmscon.git] / src / static_gl_math.c
1 /*
2  * kmscon - GL Math Helpers
3  *
4  * Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
5  * Copyright (c) 2011 University of Tuebingen
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files
9  * (the "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26
27 /*
28  * Math Helper
29  * Basic linear algebra and a matrix stack helper.
30  */
31
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include "static_gl.h"
36
37 struct gl_m4_entry {
38         struct gl_m4_entry *next;
39         float matrix[16];
40 };
41
42 struct gl_m4_stack {
43         struct gl_m4_entry stack;
44         struct gl_m4_entry *cache;
45 };
46
47 void gl_m4_identity(float *m)
48 {
49         if (!m)
50                 return;
51
52         m[0] = 1;
53         m[1] = 0;
54         m[2] = 0;
55         m[3] = 0;
56
57         m[4] = 0;
58         m[5] = 1;
59         m[6] = 0;
60         m[7] = 0;
61
62         m[8] = 0;
63         m[9] = 0;
64         m[10] = 1;
65         m[11] = 0;
66
67         m[12] = 0;
68         m[13] = 0;
69         m[14] = 0;
70         m[15] = 1;
71 }
72
73 void gl_m4_copy(float *dest, const float *src)
74 {
75         if (!dest || !src)
76                 return;
77
78         dest[0] = src[0];
79         dest[1] = src[1];
80         dest[2] = src[2];
81         dest[3] = src[3];
82
83         dest[4] = src[4];
84         dest[5] = src[5];
85         dest[6] = src[6];
86         dest[7] = src[7];
87
88         dest[8] = src[8];
89         dest[9] = src[9];
90         dest[10] = src[10];
91         dest[11] = src[11];
92
93         dest[12] = src[12];
94         dest[13] = src[13];
95         dest[14] = src[14];
96         dest[15] = src[15];
97 }
98
99 /* Matrix Multiplication
100  * This is the simplest algorithm to multiply two matrices. It computes:
101  *    dest = n * m
102  * That is, n is left side and m is right side.
103  *
104  * Matrix-multiplication is heavy, avoid it if possible.
105  */
106 void gl_m4_mult_dest(float *dest, const float *n, const float *m)
107 {
108         unsigned int row, col, j;
109
110         if (!dest || !n || !m)
111                 return;
112
113         for (row = 0; row < 4; ++row) {
114                 for (col = 0; col < 4; ++col) {
115                         dest[row * 4 + col] = 0;
116                         for (j = 0; j < 4; ++j)
117                                 dest[row * 4 + col] +=
118                                         n[row * 4 + j] * m[j * 4 + col];
119                 }
120         }
121 }
122
123 /* this computes n = n * m */
124 void gl_m4_mult(float *n, const float *m)
125 {
126         float tmp[16];
127
128         if (!n || !m)
129                 return;
130
131         gl_m4_mult_dest(tmp, n, m);
132         gl_m4_copy(n, tmp);
133 }
134
135 void gl_m4_translate(float *m, float x, float y, float z)
136 {
137         float trans[16] = { 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 };
138
139         if (!m)
140                 return;
141
142         gl_m4_mult(m, trans);
143 }
144
145 void gl_m4_scale(float *m, float x, float y, float z)
146 {
147         float scale[16] = { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 };
148
149         if (!m)
150                 return;
151
152         gl_m4_mult(m, scale);
153 }
154
155 void gl_m4_transpose_dest(float *dest, const float *src)
156 {
157         if (!dest || !src)
158                 return;
159
160         dest[0] = src[0];
161         dest[5] = src[5];
162         dest[10] = src[10];
163         dest[15] = src[15];
164
165         dest[1] = src[4];
166         dest[4] = src[1];
167
168         dest[8] = src[2];
169         dest[2] = src[8];
170
171         dest[3] = src[12];
172         dest[12] = src[3];
173
174         dest[7] = src[13];
175         dest[13] = src[7];
176
177         dest[11] = src[14];
178         dest[14] = src[11];
179
180         dest[6] = src[9];
181         dest[9] = src[6];
182 }
183
184 void gl_m4_transpose(float *m)
185 {
186         float tmp;
187
188         if (!m)
189                 return;
190
191         tmp = m[1];
192         m[1] = m[4];
193         m[4] = tmp;
194
195         tmp = m[8];
196         m[8] = m[2];
197         m[2] = tmp;
198
199         tmp = m[3];
200         m[3] = m[12];
201         m[12] = tmp;
202
203         tmp = m[7];
204         m[7] = m[13];
205         m[13] = tmp;
206
207         tmp = m[11];
208         m[11] = m[14];
209         m[14] = tmp;
210
211         tmp = m[6];
212         m[6] = m[9];
213         m[9] = tmp;
214 }
215
216 int gl_m4_stack_new(struct gl_m4_stack **out)
217 {
218         struct gl_m4_stack *stack;
219
220         if (!out)
221                 return -EINVAL;
222
223         stack = malloc(sizeof(*stack));
224         if (!stack)
225                 return -ENOMEM;
226
227         memset(stack, 0, sizeof(*stack));
228         gl_m4_identity(stack->stack.matrix);
229
230         *out = stack;
231         return 0;
232 }
233
234 void gl_m4_stack_free(struct gl_m4_stack *stack)
235 {
236         struct gl_m4_entry *tmp;
237
238         if (!stack)
239                 return;
240
241         while (stack->stack.next) {
242                 tmp = stack->stack.next;
243                 stack->stack.next = tmp->next;
244                 free(tmp);
245         }
246
247         while (stack->cache) {
248                 tmp = stack->cache;
249                 stack->cache = tmp->next;
250                 free(tmp);
251         }
252
253         free(stack);
254 }
255
256 float *gl_m4_stack_push(struct gl_m4_stack *stack)
257 {
258         struct gl_m4_entry *entry;
259
260         if (stack->cache) {
261                 entry = stack->cache;
262                 stack->cache = entry->next;
263         } else {
264                 entry = malloc(sizeof(*entry));
265                 if (!entry)
266                         return NULL;
267         }
268
269         gl_m4_copy(entry->matrix, stack->stack.matrix);
270         entry->next = stack->stack.next;
271         stack->stack.next = entry;
272
273         return stack->stack.matrix;
274 }
275
276 float *gl_m4_stack_pop(struct gl_m4_stack *stack)
277 {
278         struct gl_m4_entry *entry;
279
280         if (!stack)
281                 return NULL;
282
283         entry = stack->stack.next;
284         if (!entry) {
285                 gl_m4_identity(stack->stack.matrix);
286                 return stack->stack.matrix;
287         }
288
289         stack->stack.next = entry->next;
290         entry->next = stack->cache;
291         stack->cache = entry;
292
293         gl_m4_copy(stack->stack.matrix, entry->matrix);
294
295         return stack->stack.matrix;
296 }
297
298 float *gl_m4_stack_tip(struct gl_m4_stack *stack)
299 {
300         if (!stack)
301                 return NULL;
302
303         return stack->stack.matrix;
304 }