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