Fix keymap.
[vuplus_xbmc] / xbmc / guilib / MatrixGLES.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program 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
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21
22 #include "system.h"
23
24 #if HAS_GLES == 2
25 #include "system_gl.h"
26
27 #include <cmath>
28 #include "MatrixGLES.h"
29 #include "utils/log.h"
30 #if defined(__ARM_NEON__)
31 #include "utils/CPUInfo.h"
32 #endif
33
34 CMatrixGLES g_matrices;
35
36 #define MODE_WITHIN_RANGE(m)       ((m >= 0) && (m < (int)MM_MATRIXSIZE))
37
38 CMatrixGLES::CMatrixGLES()
39 {
40   for (unsigned int i=0; i < MM_MATRIXSIZE; i++)
41   {
42     m_matrices[i].push_back(MatrixWrapper());
43     MatrixMode((EMATRIXMODE)i);
44     LoadIdentity();
45   }
46   m_matrixMode = (EMATRIXMODE)-1;
47   m_pMatrix    = NULL;
48 #if defined(__ARM_NEON__)
49   m_has_neon = (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON) == CPU_FEATURE_NEON;
50 #endif
51 }
52
53 CMatrixGLES::~CMatrixGLES()
54 {
55 }
56
57 GLfloat* CMatrixGLES::GetMatrix(EMATRIXMODE mode)
58 {
59   if (MODE_WITHIN_RANGE(mode))
60   {
61     if (!m_matrices[mode].empty())
62     {
63       return m_matrices[mode].back();
64     }
65   }
66   return NULL;
67 }
68
69 void CMatrixGLES::MatrixMode(EMATRIXMODE mode)
70 {
71   if (MODE_WITHIN_RANGE(mode))
72   {
73     m_matrixMode = mode;
74     m_pMatrix    = m_matrices[mode].back();
75   }
76   else
77   {
78     m_matrixMode = (EMATRIXMODE)-1;
79     m_pMatrix    = NULL;
80   }
81 }
82
83 void CMatrixGLES::PushMatrix()
84 {
85   if (m_pMatrix && MODE_WITHIN_RANGE(m_matrixMode))
86   {
87     m_matrices[m_matrixMode].push_back(MatrixWrapper(m_pMatrix));
88     m_pMatrix =  m_matrices[m_matrixMode].back();
89   }
90 }
91
92 void CMatrixGLES::PopMatrix()
93 {
94   if (MODE_WITHIN_RANGE(m_matrixMode))
95   {
96     if (m_matrices[m_matrixMode].size() > 1)
97     { 
98       m_matrices[m_matrixMode].pop_back();
99     }
100     m_pMatrix = m_matrices[m_matrixMode].back();
101   }
102 }
103
104 void CMatrixGLES::LoadIdentity()
105 {
106   if (m_pMatrix)
107   {
108     m_pMatrix[0] = 1.0f;  m_pMatrix[4] = 0.0f;  m_pMatrix[8]  = 0.0f;  m_pMatrix[12] = 0.0f;
109     m_pMatrix[1] = 0.0f;  m_pMatrix[5] = 1.0f;  m_pMatrix[9]  = 0.0f;  m_pMatrix[13] = 0.0f;
110     m_pMatrix[2] = 0.0f;  m_pMatrix[6] = 0.0f;  m_pMatrix[10] = 1.0f;  m_pMatrix[14] = 0.0f;
111     m_pMatrix[3] = 0.0f;  m_pMatrix[7] = 0.0f;  m_pMatrix[11] = 0.0f;  m_pMatrix[15] = 1.0f;
112   }
113 }
114
115 void CMatrixGLES::Ortho(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
116 {
117   GLfloat u =  2.0f / (r - l);
118   GLfloat v =  2.0f / (t - b);
119   GLfloat w = -2.0f / (f - n);
120   GLfloat x = - (r + l) / (r - l);
121   GLfloat y = - (t + b) / (t - b);
122   GLfloat z = - (f + n) / (f - n);
123   GLfloat matrix[16] = {   u, 0.0f, 0.0f, 0.0f,
124                         0.0f,    v, 0.0f, 0.0f,
125                         0.0f, 0.0f,    w, 0.0f,
126                            x,    y,    z, 1.0f};
127   MultMatrixf(matrix);
128 }
129
130 void CMatrixGLES::Ortho2D(GLfloat l, GLfloat r, GLfloat b, GLfloat t)
131 {
132   GLfloat u =  2.0f / (r - l);
133   GLfloat v =  2.0f / (t - b);
134   GLfloat x = - (r + l) / (r - l);
135   GLfloat y = - (t + b) / (t - b);
136   GLfloat matrix[16] = {   u, 0.0f, 0.0f, 0.0f,
137                         0.0f,    v, 0.0f, 0.0f,
138                         0.0f, 0.0f,-1.0f, 0.0f,
139                            x,    y, 0.0f, 1.0f};
140   MultMatrixf(matrix);
141 }
142
143 void CMatrixGLES::Frustum(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
144 {
145   GLfloat u = (2.0f * n) / (r - l);
146   GLfloat v = (2.0f * n) / (t - b);
147   GLfloat w = (r + l) / (r - l);
148   GLfloat x = (t + b) / (t - b);
149   GLfloat y = - (f + n) / (f - n);
150   GLfloat z = - (2.0f * f * n) / (f - n);
151   GLfloat matrix[16] = {   u, 0.0f, 0.0f, 0.0f,
152                         0.0f,    v, 0.0f, 0.0f,
153                            w,    x,    y,-1.0f,
154                         0.0f, 0.0f,    z, 0.0f};
155   MultMatrixf(matrix);
156 }
157
158 void CMatrixGLES::Translatef(GLfloat x, GLfloat y, GLfloat z)
159 {
160   GLfloat matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
161                         0.0f, 1.0f, 0.0f, 0.0f,
162                         0.0f, 0.0f, 1.0f, 0.0f,
163                            x,    y,    z, 1.0f};
164   MultMatrixf(matrix);
165 }
166
167 void CMatrixGLES::Scalef(GLfloat x, GLfloat y, GLfloat z)
168 {
169   GLfloat matrix[16] = {   x, 0.0f, 0.0f, 0.0f,
170                         0.0f,    y, 0.0f, 0.0f,
171                         0.0f, 0.0f,    z, 0.0f,
172                         0.0f, 0.0f, 0.0f, 1.0f};
173   MultMatrixf(matrix);
174 }
175
176 void CMatrixGLES::Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
177 {
178   GLfloat modulous = sqrt((x*x)+(y*y)+(z*z));
179   if (modulous != 0.0)
180   {
181     x /= modulous;
182     y /= modulous;
183     z /= modulous;
184   }
185   GLfloat cosine = cos(angle);
186   GLfloat sine   = sin(angle);
187   GLfloat cos1   = 1 - cosine;
188   GLfloat a = (x*x*cos1) + cosine;
189   GLfloat b = (x*y*cos1) - (z*sine);
190   GLfloat c = (x*z*cos1) + (y*sine);
191   GLfloat d = (y*x*cos1) + (z*sine);
192   GLfloat e = (y*y*cos1) + cosine;
193   GLfloat f = (y*z*cos1) - (x*sine);
194   GLfloat g = (z*x*cos1) - (y*sine);
195   GLfloat h = (z*y*cos1) + (x*sine);
196   GLfloat i = (z*z*cos1) + cosine;
197   GLfloat matrix[16] = {   a,    d,    g, 0.0f,
198                            b,    e,    h, 0.0f,
199                            c,    f,    i, 0.0f,
200                         0.0f, 0.0f, 0.0f, 1.0f};
201   MultMatrixf(matrix);
202 }
203
204 #if defined(__ARM_NEON__)
205   
206 inline void Matrix4Mul(const float* src_mat_1, const float* src_mat_2, float* dst_mat)
207 {
208   asm volatile (
209     // Store A & B leaving room at top of registers for result (q0-q3)
210     "vldmia %1, { q4-q7 }  \n\t"
211     "vldmia %2, { q8-q11 } \n\t"
212
213     // result = first column of B x first row of A
214     "vmul.f32 q0, q8, d8[0]\n\t"
215     "vmul.f32 q1, q8, d10[0]\n\t"
216     "vmul.f32 q2, q8, d12[0]\n\t"
217     "vmul.f32 q3, q8, d14[0]\n\t"
218
219     // result += second column of B x second row of A
220     "vmla.f32 q0, q9, d8[1]\n\t"
221     "vmla.f32 q1, q9, d10[1]\n\t"
222     "vmla.f32 q2, q9, d12[1]\n\t"
223     "vmla.f32 q3, q9, d14[1]\n\t"
224
225     // result += third column of B x third row of A
226     "vmla.f32 q0, q10, d9[0]\n\t"
227     "vmla.f32 q1, q10, d11[0]\n\t"
228     "vmla.f32 q2, q10, d13[0]\n\t"
229     "vmla.f32 q3, q10, d15[0]\n\t"
230
231     // result += last column of B x last row of A
232     "vmla.f32 q0, q11, d9[1]\n\t"
233     "vmla.f32 q1, q11, d11[1]\n\t"
234     "vmla.f32 q2, q11, d13[1]\n\t"
235     "vmla.f32 q3, q11, d15[1]\n\t"
236
237     // output = result registers
238     "vstmia %2, { q0-q3 }"
239     : //no output 
240     : "r" (dst_mat), "r" (src_mat_2), "r" (src_mat_1)       // input - note *value* of pointer doesn't change
241     : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11" //clobber
242     );
243 }
244 #endif
245 void CMatrixGLES::MultMatrixf(const GLfloat *matrix)
246 {
247   if (m_pMatrix)
248   {
249 #if defined(__ARM_NEON__)
250     if (m_has_neon)
251     {
252       GLfloat m[16];
253       Matrix4Mul(m_pMatrix, matrix, m);
254       return;
255     }
256 #endif
257     GLfloat a = (matrix[0]  * m_pMatrix[0]) + (matrix[1]  * m_pMatrix[4]) + (matrix[2]  * m_pMatrix[8])  + (matrix[3]  * m_pMatrix[12]);
258     GLfloat b = (matrix[0]  * m_pMatrix[1]) + (matrix[1]  * m_pMatrix[5]) + (matrix[2]  * m_pMatrix[9])  + (matrix[3]  * m_pMatrix[13]);
259     GLfloat c = (matrix[0]  * m_pMatrix[2]) + (matrix[1]  * m_pMatrix[6]) + (matrix[2]  * m_pMatrix[10]) + (matrix[3]  * m_pMatrix[14]);
260     GLfloat d = (matrix[0]  * m_pMatrix[3]) + (matrix[1]  * m_pMatrix[7]) + (matrix[2]  * m_pMatrix[11]) + (matrix[3]  * m_pMatrix[15]);
261     GLfloat e = (matrix[4]  * m_pMatrix[0]) + (matrix[5]  * m_pMatrix[4]) + (matrix[6]  * m_pMatrix[8])  + (matrix[7]  * m_pMatrix[12]);
262     GLfloat f = (matrix[4]  * m_pMatrix[1]) + (matrix[5]  * m_pMatrix[5]) + (matrix[6]  * m_pMatrix[9])  + (matrix[7]  * m_pMatrix[13]);
263     GLfloat g = (matrix[4]  * m_pMatrix[2]) + (matrix[5]  * m_pMatrix[6]) + (matrix[6]  * m_pMatrix[10]) + (matrix[7]  * m_pMatrix[14]);
264     GLfloat h = (matrix[4]  * m_pMatrix[3]) + (matrix[5]  * m_pMatrix[7]) + (matrix[6]  * m_pMatrix[11]) + (matrix[7]  * m_pMatrix[15]);
265     GLfloat i = (matrix[8]  * m_pMatrix[0]) + (matrix[9]  * m_pMatrix[4]) + (matrix[10] * m_pMatrix[8])  + (matrix[11] * m_pMatrix[12]);
266     GLfloat j = (matrix[8]  * m_pMatrix[1]) + (matrix[9]  * m_pMatrix[5]) + (matrix[10] * m_pMatrix[9])  + (matrix[11] * m_pMatrix[13]);
267     GLfloat k = (matrix[8]  * m_pMatrix[2]) + (matrix[9]  * m_pMatrix[6]) + (matrix[10] * m_pMatrix[10]) + (matrix[11] * m_pMatrix[14]);
268     GLfloat l = (matrix[8]  * m_pMatrix[3]) + (matrix[9]  * m_pMatrix[7]) + (matrix[10] * m_pMatrix[11]) + (matrix[11] * m_pMatrix[15]);
269     GLfloat m = (matrix[12] * m_pMatrix[0]) + (matrix[13] * m_pMatrix[4]) + (matrix[14] * m_pMatrix[8])  + (matrix[15] * m_pMatrix[12]);
270     GLfloat n = (matrix[12] * m_pMatrix[1]) + (matrix[13] * m_pMatrix[5]) + (matrix[14] * m_pMatrix[9])  + (matrix[15] * m_pMatrix[13]);
271     GLfloat o = (matrix[12] * m_pMatrix[2]) + (matrix[13] * m_pMatrix[6]) + (matrix[14] * m_pMatrix[10]) + (matrix[15] * m_pMatrix[14]);
272     GLfloat p = (matrix[12] * m_pMatrix[3]) + (matrix[13] * m_pMatrix[7]) + (matrix[14] * m_pMatrix[11]) + (matrix[15] * m_pMatrix[15]);
273     m_pMatrix[0] = a;  m_pMatrix[4] = e;  m_pMatrix[8]  = i;  m_pMatrix[12] = m;
274     m_pMatrix[1] = b;  m_pMatrix[5] = f;  m_pMatrix[9]  = j;  m_pMatrix[13] = n;
275     m_pMatrix[2] = c;  m_pMatrix[6] = g;  m_pMatrix[10] = k;  m_pMatrix[14] = o;
276     m_pMatrix[3] = d;  m_pMatrix[7] = h;  m_pMatrix[11] = l;  m_pMatrix[15] = p;
277   }
278 }
279
280 // gluLookAt implementation taken from Mesa3D
281 void CMatrixGLES::LookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx, GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy, GLfloat upz)
282 {
283   GLfloat forward[3], side[3], up[3];
284   GLfloat m[4][4];
285
286   forward[0] = centerx - eyex;
287   forward[1] = centery - eyey;
288   forward[2] = centerz - eyez;
289
290   up[0] = upx;
291   up[1] = upy;
292   up[2] = upz;
293
294   GLfloat tmp = sqrt(forward[0]*forward[0] + forward[1]*forward[1] + forward[2]*forward[2]);
295   if (tmp != 0.0)
296   {
297     forward[0] /= tmp;
298     forward[1] /= tmp;
299     forward[2] /= tmp;
300   }
301
302   side[0] = forward[1]*up[2] - forward[2]*up[1];
303   side[1] = forward[2]*up[0] - forward[0]*up[2];
304   side[2] = forward[0]*up[1] - forward[1]*up[0];
305
306   tmp = sqrt(side[0]*side[0] + side[1]*side[1] + side[2]*side[2]);
307   if (tmp != 0.0)
308   {
309     side[0] /= tmp;
310     side[1] /= tmp;
311     side[2] /= tmp;
312   }
313
314   up[0] = side[1]*forward[2] - side[2]*forward[1];
315   up[1] = side[2]*forward[0] - side[0]*forward[2];
316   up[2] = side[0]*forward[1] - side[1]*forward[0];
317
318   m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f;
319   m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = 0.0f;
320   m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = 0.0f;
321   m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
322
323   m[0][0] = side[0];
324   m[1][0] = side[1];
325   m[2][0] = side[2];
326
327   m[0][1] = up[0];
328   m[1][1] = up[1];
329   m[2][1] = up[2];
330
331   m[0][2] = -forward[0];
332   m[1][2] = -forward[1];
333   m[2][2] = -forward[2];
334
335   MultMatrixf(&m[0][0]);
336   Translatef(-eyex, -eyey, -eyez);
337 }
338
339 static void __gluMultMatrixVecf(const GLfloat matrix[16], const GLfloat in[4], GLfloat out[4])
340 {
341   int i;
342
343   for (i=0; i<4; i++)
344   {
345     out[i] = in[0] * matrix[0*4+i] +
346              in[1] * matrix[1*4+i] +
347              in[2] * matrix[2*4+i] +
348              in[3] * matrix[3*4+i];
349   }
350 }
351
352 // gluProject implementation taken from Mesa3D
353 bool CMatrixGLES::Project(GLfloat objx, GLfloat objy, GLfloat objz, const GLfloat modelMatrix[16], const GLfloat projMatrix[16], const GLint viewport[4], GLfloat* winx, GLfloat* winy, GLfloat* winz)
354 {
355   GLfloat in[4];
356   GLfloat out[4];
357
358   in[0]=objx;
359   in[1]=objy;
360   in[2]=objz;
361   in[3]=1.0;
362   __gluMultMatrixVecf(modelMatrix, in, out);
363   __gluMultMatrixVecf(projMatrix, out, in);
364   if (in[3] == 0.0)
365     return false;
366   in[0] /= in[3];
367   in[1] /= in[3];
368   in[2] /= in[3];
369   /* Map x, y and z to range 0-1 */
370   in[0] = in[0] * 0.5 + 0.5;
371   in[1] = in[1] * 0.5 + 0.5;
372   in[2] = in[2] * 0.5 + 0.5;
373
374   /* Map x,y to viewport */
375   in[0] = in[0] * viewport[2] + viewport[0];
376   in[1] = in[1] * viewport[3] + viewport[1];
377
378   *winx=in[0];
379   *winy=in[1];
380   *winz=in[2];
381   return true;
382 }
383
384 void CMatrixGLES::PrintMatrix(void)
385 {
386   for (unsigned int i=0; i < MM_MATRIXSIZE; i++)
387   {
388     GLfloat *m = GetMatrix((EMATRIXMODE)i);
389     CLog::Log(LOGDEBUG, "MatrixGLES - Matrix:%d", i);
390     CLog::Log(LOGDEBUG, "%f %f %f %f", m[0], m[4], m[8],  m[12]);
391     CLog::Log(LOGDEBUG, "%f %f %f %f", m[1], m[5], m[9],  m[13]);
392     CLog::Log(LOGDEBUG, "%f %f %f %f", m[2], m[6], m[10], m[14]);
393     CLog::Log(LOGDEBUG, "%f %f %f %f", m[3], m[7], m[11], m[15]);
394   }
395 }
396
397 #endif