~oem-solutions-group/unity-2d/clutter-1.0

« back to all changes in this revision

Viewing changes to clutter/cogl/common/cogl-current-matrix.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20100321132756-nf8yd30yxo3zzwcm
Tags: upstream-1.2.2
ImportĀ upstreamĀ versionĀ 1.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Cogl
3
 
 *
4
 
 * An object oriented GL/GLES Abstraction/Utility Layer
5
 
 *
6
 
 * Copyright (C) 2009 Intel Corporation.
7
 
 *
8
 
 * This library is free software; you can redistribute it and/or
9
 
 * modify it under the terms of the GNU Lesser General Public
10
 
 * License as published by the Free Software Foundation; either
11
 
 * version 2 of the License, or (at your option) any later version.
12
 
 *
13
 
 * This library is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 
 * Lesser General Public License for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU Lesser General Public
19
 
 * License along with this library; if not, write to the
20
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
 
 * Boston, MA 02111-1307, USA.
22
 
 *
23
 
 * Authors:
24
 
 *   Havoc Pennington <hp@pobox.com> for litl
25
 
 *   Robert Bragg     <robert@linux.intel.com>
26
 
 */
27
 
 
28
 
#ifdef HAVE_CONFIG_H
29
 
#include "config.h"
30
 
#endif
31
 
 
32
 
#include "cogl.h"
33
 
#include "cogl-context.h"
34
 
#include "cogl-internal.h"
35
 
#include "cogl-current-matrix.h"
36
 
#include "cogl-matrix-stack.h"
37
 
 
38
 
#ifdef HAVE_COGL_GLES2
39
 
#include "cogl-gles2-wrapper.h"
40
 
 
41
 
#define glFrustum(L,R,B,T,N,F) \
42
 
            cogl_wrap_glFrustumf((GLfloat)L, (GLfloat)R, (GLfloat)B, \
43
 
                                 (GLfloat)T, (GLfloat)N, (GLfloat)F)
44
 
#elif defined (HAVE_COGL_GLES)
45
 
 
46
 
#define glFrustum(L,R,B,T,N,F) \
47
 
            glFrustumf((GLfloat)L, (GLfloat)R, (GLfloat)B, \
48
 
                       (GLfloat)T, (GLfloat)N, (GLfloat)F)
49
 
 
50
 
#define glOrtho glOrthof
51
 
 
52
 
#endif
53
 
 
54
 
#include <string.h>
55
 
#include <math.h>
56
 
 
57
 
static void
58
 
_cogl_get_client_stack (CoglContext      *ctx,
59
 
                        CoglMatrixMode    mode,
60
 
                        CoglMatrixStack **current_stack_p)
61
 
{
62
 
  if (ctx->modelview_stack &&
63
 
      mode == COGL_MATRIX_MODELVIEW)
64
 
    *current_stack_p  = ctx->modelview_stack;
65
 
  else if (ctx->projection_stack &&
66
 
           mode == COGL_MATRIX_PROJECTION)
67
 
    *current_stack_p  = ctx->projection_stack;
68
 
  else
69
 
    *current_stack_p = NULL;
70
 
}
71
 
 
72
 
#define _COGL_GET_CONTEXT_AND_STACK(contextvar, stackvar, rval) \
73
 
  CoglMatrixStack *stackvar;                                    \
74
 
  _COGL_GET_CONTEXT (contextvar, rval);                         \
75
 
  _cogl_get_client_stack (contextvar, ctx->matrix_mode, &stackvar)
76
 
 
77
 
void
78
 
_cogl_set_current_matrix (CoglMatrixMode mode)
79
 
{
80
 
  GLenum gl_mode;
81
 
  CoglMatrixStack *current_stack;                                    \
82
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
83
 
 
84
 
  if (mode == ctx->matrix_mode)
85
 
    return;
86
 
  ctx->matrix_mode = mode;
87
 
 
88
 
  /* If we have a client side stack then then the GL matrix mode only needs
89
 
   * changing when we come to flush it to OpenGL */
90
 
  _cogl_get_client_stack (ctx, mode, &current_stack);
91
 
  if (current_stack)
92
 
    return;
93
 
 
94
 
  gl_mode = 0; /* silence compiler warning */
95
 
  switch (mode)
96
 
    {
97
 
    case COGL_MATRIX_MODELVIEW:
98
 
      gl_mode = GL_MODELVIEW;
99
 
      break;
100
 
    case COGL_MATRIX_PROJECTION:
101
 
      gl_mode = GL_PROJECTION;
102
 
      break;
103
 
    case COGL_MATRIX_TEXTURE:
104
 
      gl_mode = GL_TEXTURE;
105
 
      break;
106
 
    }
107
 
 
108
 
  GE (glMatrixMode (gl_mode));
109
 
}
110
 
 
111
 
void
112
 
_cogl_current_matrix_push (void)
113
 
{
114
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
115
 
 
116
 
  if (current_stack != NULL)
117
 
    _cogl_matrix_stack_push (current_stack);
118
 
  else
119
 
    GE (glPushMatrix ());
120
 
}
121
 
 
122
 
void
123
 
_cogl_current_matrix_pop (void)
124
 
{
125
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
126
 
 
127
 
  if (current_stack != NULL)
128
 
    _cogl_matrix_stack_pop (current_stack);
129
 
  else
130
 
    GE (glPopMatrix ());
131
 
}
132
 
 
133
 
void
134
 
_cogl_current_matrix_identity (void)
135
 
{
136
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
137
 
 
138
 
  if (current_stack != NULL)
139
 
    _cogl_matrix_stack_load_identity (current_stack);
140
 
  else
141
 
    GE (glLoadIdentity ());
142
 
}
143
 
 
144
 
void
145
 
_cogl_current_matrix_load (const CoglMatrix *matrix)
146
 
{
147
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
148
 
 
149
 
  if (current_stack != NULL)
150
 
    _cogl_matrix_stack_set (current_stack, matrix);
151
 
  else
152
 
    GE (glLoadMatrixf (cogl_matrix_get_array (matrix)));
153
 
}
154
 
 
155
 
void
156
 
_cogl_current_matrix_multiply (const CoglMatrix *matrix)
157
 
{
158
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
159
 
 
160
 
  if (current_stack != NULL)
161
 
    _cogl_matrix_stack_multiply (current_stack, matrix);
162
 
  else
163
 
    GE (glMultMatrixf (cogl_matrix_get_array (matrix)));
164
 
}
165
 
 
166
 
void
167
 
_cogl_current_matrix_rotate (float angle,
168
 
                             float x,
169
 
                             float y,
170
 
                             float z)
171
 
{
172
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
173
 
 
174
 
  if (current_stack != NULL)
175
 
    _cogl_matrix_stack_rotate (current_stack, angle, x, y, z);
176
 
  else
177
 
    GE (glRotatef (angle, x, y, z));
178
 
}
179
 
 
180
 
void
181
 
_cogl_current_matrix_scale (float x,
182
 
                            float y,
183
 
                            float z)
184
 
{
185
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
186
 
 
187
 
  if (current_stack != NULL)
188
 
    _cogl_matrix_stack_scale (current_stack, x, y, z);
189
 
  else
190
 
    GE (glScalef (x, y, z));
191
 
}
192
 
 
193
 
void
194
 
_cogl_current_matrix_translate (float x,
195
 
                                float y,
196
 
                                float z)
197
 
{
198
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
199
 
 
200
 
  if (current_stack != NULL)
201
 
    _cogl_matrix_stack_translate (current_stack, x, y, z);
202
 
  else
203
 
    GE (glTranslatef (x, y, z));
204
 
}
205
 
 
206
 
void
207
 
_cogl_current_matrix_frustum (float left,
208
 
                              float right,
209
 
                              float bottom,
210
 
                              float top,
211
 
                              float near_val,
212
 
                              float far_val)
213
 
{
214
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
215
 
 
216
 
  if (current_stack != NULL)
217
 
    _cogl_matrix_stack_frustum (current_stack,
218
 
                                left, right,
219
 
                                bottom, top,
220
 
                                near_val,
221
 
                                far_val);
222
 
  else
223
 
    GE (glFrustum (left, right, bottom, top, near_val, far_val));
224
 
}
225
 
 
226
 
void
227
 
_cogl_current_matrix_perspective (float fov_y,
228
 
                                  float aspect,
229
 
                                  float z_near,
230
 
                                  float z_far)
231
 
{
232
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
233
 
 
234
 
  if (current_stack != NULL)
235
 
    _cogl_matrix_stack_perspective (current_stack,
236
 
                                    fov_y, aspect, z_near, z_far);
237
 
  else
238
 
    {
239
 
      /* NB: There is no glPerspective() (only gluPerspective()) so we use
240
 
       * cogl_matrix_perspective: */
241
 
      CoglMatrix matrix;
242
 
      _cogl_get_matrix (ctx->matrix_mode, &matrix);
243
 
      cogl_matrix_perspective (&matrix,
244
 
                               fov_y, aspect, z_near, z_far);
245
 
      _cogl_current_matrix_load (&matrix);
246
 
    }
247
 
}
248
 
 
249
 
void
250
 
_cogl_current_matrix_ortho (float left,
251
 
                            float right,
252
 
                            float bottom,
253
 
                            float top,
254
 
                            float near_val,
255
 
                            float far_val)
256
 
{
257
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
258
 
 
259
 
  if (current_stack != NULL)
260
 
    _cogl_matrix_stack_ortho (current_stack,
261
 
                              left, right,
262
 
                              bottom, top,
263
 
                              near_val,
264
 
                              far_val);
265
 
  else
266
 
    {
267
 
#ifdef HAVE_COGL_GLES2
268
 
      /* NB: GLES 2 has no glOrtho(): */
269
 
      CoglMatrix matrix;
270
 
      _cogl_get_matrix (ctx->matrix_mode, &matrix);
271
 
      cogl_matrix_ortho (&matrix,
272
 
                         left, right, bottom, top, near_val, far_val);
273
 
      _cogl_current_matrix_load (&matrix);
274
 
#else
275
 
      GE (glOrtho (left, right, bottom, top, near_val, far_val));
276
 
#endif
277
 
    }
278
 
}
279
 
 
280
 
void
281
 
_cogl_get_matrix (CoglMatrixMode mode,
282
 
                  CoglMatrix    *matrix)
283
 
{
284
 
  CoglMatrixStack *current_stack;
285
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
286
 
 
287
 
  _cogl_get_client_stack (ctx, mode, &current_stack);
288
 
 
289
 
  if (current_stack)
290
 
    _cogl_matrix_stack_get (current_stack, matrix);
291
 
  else
292
 
    {
293
 
      GLenum gl_mode;
294
 
      GLfloat gl_matrix[16];
295
 
 
296
 
      gl_mode = 0; /* silence compiler warning */
297
 
      switch (mode)
298
 
        {
299
 
        case COGL_MATRIX_MODELVIEW:
300
 
          gl_mode = GL_MODELVIEW_MATRIX;
301
 
          break;
302
 
        case COGL_MATRIX_PROJECTION:
303
 
          gl_mode = GL_PROJECTION_MATRIX;
304
 
          break;
305
 
        case COGL_MATRIX_TEXTURE:
306
 
          gl_mode = GL_TEXTURE_MATRIX;
307
 
          break;
308
 
        }
309
 
 
310
 
      /* Note: we have a redundant copy happening here. If that turns out to be
311
 
       * a problem then, since this is internal to Cogl, we could pass the
312
 
       * CoglMatrix pointer directly to glGetFloatv; the only problem with that
313
 
       * is that if we later add internal flags to CoglMatrix they will need to
314
 
       * be initialized seperatly.
315
 
       */
316
 
      GE (glGetFloatv (gl_mode, gl_matrix));
317
 
      cogl_matrix_init_from_array (matrix, gl_matrix);
318
 
    }
319
 
}
320
 
 
321
 
void
322
 
_cogl_set_matrix (const CoglMatrix *matrix)
323
 
{
324
 
  _cogl_current_matrix_load (matrix);
325
 
}
326
 
 
327
 
void
328
 
_cogl_current_matrix_state_init (void)
329
 
{
330
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
331
 
 
332
 
  ctx->matrix_mode = COGL_MATRIX_MODELVIEW;
333
 
  ctx->modelview_stack = NULL;
334
 
  ctx->projection_stack = NULL;
335
 
 
336
 
#if 0
337
 
  if (ctx->indirect ||
338
 
      cogl_debug_flags & COGL_DEBUG_FORCE_CLIENT_SIDE_MATRICES)
339
 
#endif
340
 
    {
341
 
      ctx->modelview_stack = _cogl_matrix_stack_new ();
342
 
      ctx->projection_stack = _cogl_matrix_stack_new ();
343
 
    }
344
 
}
345
 
 
346
 
void
347
 
_cogl_current_matrix_state_destroy (void)
348
 
{
349
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
350
 
 
351
 
  if (current_stack)
352
 
    _cogl_matrix_stack_destroy (current_stack);
353
 
}
354
 
 
355
 
void
356
 
_cogl_current_matrix_state_flush (void)
357
 
{
358
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
359
 
 
360
 
  if (ctx->matrix_mode != COGL_MATRIX_MODELVIEW &&
361
 
      ctx->matrix_mode != COGL_MATRIX_PROJECTION)
362
 
    {
363
 
      g_warning ("matrix state must be flushed in "
364
 
                 "MODELVIEW or PROJECTION mode");
365
 
      return;
366
 
    }
367
 
 
368
 
  if (ctx->modelview_stack &&
369
 
      ctx->matrix_mode == COGL_MATRIX_MODELVIEW)
370
 
    {
371
 
      _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack,
372
 
                                      GL_MODELVIEW);
373
 
    }
374
 
  else if (ctx->projection_stack &&
375
 
           ctx->matrix_mode == COGL_MATRIX_PROJECTION)
376
 
    {
377
 
      _cogl_matrix_stack_flush_to_gl (ctx->projection_stack,
378
 
                                      GL_PROJECTION);
379
 
    }
380
 
}
381
 
 
382
 
void
383
 
_cogl_current_matrix_state_dirty (void)
384
 
{
385
 
  _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
386
 
 
387
 
  if (current_stack)
388
 
    _cogl_matrix_stack_dirty (current_stack);
389
 
}
390
 
 
391
 
void
392
 
cogl_push_matrix (void)
393
 
{
394
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
395
 
  _cogl_current_matrix_push ();
396
 
}
397
 
 
398
 
void
399
 
cogl_pop_matrix (void)
400
 
{
401
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
402
 
  _cogl_current_matrix_pop ();
403
 
}
404
 
 
405
 
void
406
 
cogl_scale (float x, float y, float z)
407
 
{
408
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
409
 
  _cogl_current_matrix_scale (x, y, z);
410
 
}
411
 
 
412
 
void
413
 
cogl_translate (float x, float y, float z)
414
 
{
415
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
416
 
  _cogl_current_matrix_translate (x, y, z);
417
 
}
418
 
 
419
 
void
420
 
cogl_rotate (float angle, float x, float y, float z)
421
 
{
422
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
423
 
  _cogl_current_matrix_rotate (angle, x, y, z);
424
 
}
425
 
 
426
 
void
427
 
cogl_perspective (float fov_y,
428
 
                  float aspect,
429
 
                  float z_near,
430
 
                  float z_far)
431
 
{
432
 
  float ymax = z_near * tanf (fov_y * G_PI / 360.0);
433
 
 
434
 
  cogl_frustum (-ymax * aspect,  /* left */
435
 
                ymax * aspect,   /* right */
436
 
                -ymax,           /* bottom */
437
 
                ymax,            /* top */
438
 
                z_near,
439
 
                z_far);
440
 
}
441
 
 
442
 
void
443
 
cogl_frustum (float        left,
444
 
              float        right,
445
 
              float        bottom,
446
 
              float        top,
447
 
              float        z_near,
448
 
              float        z_far)
449
 
{
450
 
  float c, d;
451
 
 
452
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
453
 
 
454
 
  _cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
455
 
  _cogl_current_matrix_identity ();
456
 
 
457
 
  _cogl_current_matrix_frustum (left,
458
 
                                right,
459
 
                                bottom,
460
 
                                top,
461
 
                                z_near,
462
 
                                z_far);
463
 
 
464
 
  /* Calculate and store the inverse of the matrix */
465
 
  memset (ctx->inverse_projection, 0, sizeof (float) * 16);
466
 
 
467
 
  c = - (z_far + z_near) /  (z_far - z_near);
468
 
  d = - (2 * (z_far * z_near)) /  (z_far - z_near);
469
 
 
470
 
#define M(row,col)  ctx->inverse_projection[col*4+row]
471
 
  M(0,0) =  (right - left) /  (2 * z_near);
472
 
  M(0,3) =  (right + left) /  (2 * z_near);
473
 
  M(1,1) =  (top - bottom) /  (2 * z_near);
474
 
  M(1,3) =  (top + bottom) /  (2 * z_near);
475
 
  M(2,3) = -1.0;
476
 
  M(3,2) = 1.0 / d;
477
 
  M(3,3) = c / d;
478
 
#undef M
479
 
 
480
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
481
 
}
482
 
 
483
 
void
484
 
cogl_ortho (float left,
485
 
            float right,
486
 
            float bottom,
487
 
            float top,
488
 
            float z_near,
489
 
            float z_far)
490
 
{
491
 
  CoglMatrix ortho;
492
 
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
493
 
 
494
 
  cogl_matrix_init_identity (&ortho);
495
 
  cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
496
 
  _cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
497
 
  _cogl_current_matrix_load (&ortho);
498
 
 
499
 
  /* Calculate and store the inverse of the matrix */
500
 
  memset (ctx->inverse_projection, 0, sizeof (float) * 16);
501
 
 
502
 
#define M(row,col)  ctx->inverse_projection[col*4+row]
503
 
  M(0,0) =  1.0 / ortho.xx;
504
 
  M(0,3) =  -ortho.xw;
505
 
  M(1,1) =  1.0 / ortho.yy;
506
 
  M(1,3) =  -ortho.yw;
507
 
  M(2,2) =  1.0 / ortho.zz;
508
 
  M(2,3) =  -ortho.zw;
509
 
  M(3,3) =  1.0;
510
 
#undef M
511
 
}
512
 
 
513
 
void
514
 
cogl_get_modelview_matrix (CoglMatrix *matrix)
515
 
{
516
 
  _cogl_get_matrix (COGL_MATRIX_MODELVIEW,
517
 
                    matrix);
518
 
}
519
 
 
520
 
void
521
 
cogl_set_modelview_matrix (CoglMatrix *matrix)
522
 
{
523
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
524
 
  _cogl_current_matrix_load (matrix);
525
 
}
526
 
 
527
 
void
528
 
cogl_get_projection_matrix (CoglMatrix *matrix)
529
 
{
530
 
  _cogl_get_matrix (COGL_MATRIX_PROJECTION,
531
 
                    matrix);
532
 
}
533
 
 
534
 
void
535
 
cogl_set_projection_matrix (CoglMatrix *matrix)
536
 
{
537
 
  _cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
538
 
  _cogl_current_matrix_load (matrix);
539
 
}
540
 
 
541
 
void
542
 
_cogl_flush_matrix_stacks (void)
543
 
{
544
 
  _cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
545
 
  _cogl_current_matrix_state_flush ();
546
 
  _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
547
 
  _cogl_current_matrix_state_flush ();
548
 
}
549