2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
25 #include "system_gl.h"
28 #include "MatrixGLES.h"
29 #include "utils/log.h"
30 #if defined(__ARM_NEON__)
31 #include "utils/CPUInfo.h"
34 CMatrixGLES g_matrices;
36 #define MODE_WITHIN_RANGE(m) ((m >= 0) && (m < (int)MM_MATRIXSIZE))
38 CMatrixGLES::CMatrixGLES()
40 for (unsigned int i=0; i < MM_MATRIXSIZE; i++)
42 m_matrices[i].push_back(MatrixWrapper());
43 MatrixMode((EMATRIXMODE)i);
46 m_matrixMode = (EMATRIXMODE)-1;
48 #if defined(__ARM_NEON__)
49 m_has_neon = (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON) == CPU_FEATURE_NEON;
53 CMatrixGLES::~CMatrixGLES()
57 GLfloat* CMatrixGLES::GetMatrix(EMATRIXMODE mode)
59 if (MODE_WITHIN_RANGE(mode))
61 if (!m_matrices[mode].empty())
63 return m_matrices[mode].back();
69 void CMatrixGLES::MatrixMode(EMATRIXMODE mode)
71 if (MODE_WITHIN_RANGE(mode))
74 m_pMatrix = m_matrices[mode].back();
78 m_matrixMode = (EMATRIXMODE)-1;
83 void CMatrixGLES::PushMatrix()
85 if (m_pMatrix && MODE_WITHIN_RANGE(m_matrixMode))
87 m_matrices[m_matrixMode].push_back(MatrixWrapper(m_pMatrix));
88 m_pMatrix = m_matrices[m_matrixMode].back();
92 void CMatrixGLES::PopMatrix()
94 if (MODE_WITHIN_RANGE(m_matrixMode))
96 if (m_matrices[m_matrixMode].size() > 1)
98 m_matrices[m_matrixMode].pop_back();
100 m_pMatrix = m_matrices[m_matrixMode].back();
104 void CMatrixGLES::LoadIdentity()
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;
115 void CMatrixGLES::Ortho(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
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,
130 void CMatrixGLES::Ortho2D(GLfloat l, GLfloat r, GLfloat b, GLfloat t)
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,
138 0.0f, 0.0f,-1.0f, 0.0f,
143 void CMatrixGLES::Frustum(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
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,
154 0.0f, 0.0f, z, 0.0f};
158 void CMatrixGLES::Translatef(GLfloat x, GLfloat y, GLfloat z)
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,
167 void CMatrixGLES::Scalef(GLfloat x, GLfloat y, GLfloat z)
169 GLfloat matrix[16] = { x, 0.0f, 0.0f, 0.0f,
172 0.0f, 0.0f, 0.0f, 1.0f};
176 void CMatrixGLES::Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
178 GLfloat modulous = sqrt((x*x)+(y*y)+(z*z));
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,
200 0.0f, 0.0f, 0.0f, 1.0f};
204 #if defined(__ARM_NEON__)
206 inline void Matrix4Mul(const float* src_mat_1, const float* src_mat_2, float* dst_mat)
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"
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"
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"
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"
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"
237 // output = result registers
238 "vstmia %2, { q0-q3 }"
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
245 void CMatrixGLES::MultMatrixf(const GLfloat *matrix)
249 #if defined(__ARM_NEON__)
253 Matrix4Mul(m_pMatrix, matrix, m);
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;
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)
283 GLfloat forward[3], side[3], up[3];
286 forward[0] = centerx - eyex;
287 forward[1] = centery - eyey;
288 forward[2] = centerz - eyez;
294 GLfloat tmp = sqrt(forward[0]*forward[0] + forward[1]*forward[1] + forward[2]*forward[2]);
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];
306 tmp = sqrt(side[0]*side[0] + side[1]*side[1] + side[2]*side[2]);
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];
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;
331 m[0][2] = -forward[0];
332 m[1][2] = -forward[1];
333 m[2][2] = -forward[2];
335 MultMatrixf(&m[0][0]);
336 Translatef(-eyex, -eyey, -eyez);
339 static void __gluMultMatrixVecf(const GLfloat matrix[16], const GLfloat in[4], GLfloat out[4])
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];
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)
362 __gluMultMatrixVecf(modelMatrix, in, out);
363 __gluMultMatrixVecf(projMatrix, out, in);
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;
374 /* Map x,y to viewport */
375 in[0] = in[0] * viewport[2] + viewport[0];
376 in[1] = in[1] * viewport[3] + viewport[1];
384 void CMatrixGLES::PrintMatrix(void)
386 for (unsigned int i=0; i < MM_MATRIXSIZE; i++)
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]);