diff --git a/clutter/cogl/cogl-matrix.h b/clutter/cogl/cogl-matrix.h index c8396cf44..9bf0e802e 100644 --- a/clutter/cogl/cogl-matrix.h +++ b/clutter/cogl/cogl-matrix.h @@ -151,6 +151,27 @@ void cogl_matrix_scale (CoglMatrix *matrix, float sy, float sz); +/** + * cogl_matrix_frustum: + * @matrix: A 4x4 transformation matrix + * @left: coord of left vertical clipping plane + * @right: coord of right vertical clipping plane + * @bottom: coord of bottom horizontal clipping plane + * @top: coord of top horizontal clipping plane + * @near: positive distance to near depth clipping plane + * @far: positive distance to far depth clipping plane + * + * Multiplies the matrix by the given frustum perspective matrix. + * + */ +void cogl_matrix_frustum (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far); + /** * cogl_matrix_transform_point: * @matrix: A 4x4 transformation matrix diff --git a/clutter/cogl/cogl.h.in b/clutter/cogl/cogl.h.in index 662ffc74b..5b5347c16 100644 --- a/clutter/cogl/cogl.h.in +++ b/clutter/cogl/cogl.h.in @@ -563,6 +563,24 @@ void cogl_clip_stack_save (void); */ void cogl_clip_stack_restore (void); +/** + * cogl_flush_gl_state: + * @flags: flags controlling what is flushed; currently unused, pass in 0 + * + * As an optimization, COGL functions may not immediately modify GL's + * state, instead batching up changes and applying them "just in + * time." Unapplied state could include glEnable() flags and the + * current transformation matrix among other examples. If you want to + * use GL directly, you need to flush any state COGL may have kept + * around. cogl_flush_gl_state() syncs all of COGL's state to GL. + * + * Since: 1.0 + */ +void cogl_flush_gl_state (int flags); + +/* private */ +void _cogl_set_indirect_context (gboolean indirect); + G_END_DECLS #undef __COGL_H_INSIDE__ diff --git a/clutter/cogl/common/Makefile.am b/clutter/cogl/common/Makefile.am index 7a322326a..4d0ab0a93 100644 --- a/clutter/cogl/common/Makefile.am +++ b/clutter/cogl/common/Makefile.am @@ -24,6 +24,8 @@ libclutter_cogl_common_la_SOURCES = \ cogl-bitmap.h \ cogl-bitmap.c \ cogl-bitmap-fallback.c \ + cogl-current-matrix.c \ + cogl-current-matrix.h \ cogl-primitives.h \ cogl-primitives.c \ cogl-bitmap-pixbuf.c \ @@ -34,6 +36,8 @@ libclutter_cogl_common_la_SOURCES = \ cogl-vertex-buffer-private.h \ cogl-vertex-buffer.c \ cogl-matrix.c \ + cogl-matrix-stack.c \ + cogl-matrix-stack.h \ cogl-material.c \ cogl-material-private.h \ cogl-debug.c diff --git a/clutter/cogl/common/cogl-current-matrix.c b/clutter/cogl/common/cogl-current-matrix.c new file mode 100644 index 000000000..c6a555a1a --- /dev/null +++ b/clutter/cogl/common/cogl-current-matrix.c @@ -0,0 +1,452 @@ +/* + * Clutter COGL + * + * A basic GL/GLES Abstraction/Utility Layer + * + * Authored By Havoc Pennington for litl + * + * Copyright (C) 2009 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "cogl.h" +#include "cogl-context.h" +#include "cogl-internal.h" +#include "cogl-current-matrix.h" +#include "cogl-matrix-stack.h" + +#include +#include + +void +_cogl_set_current_matrix (CoglMatrixMode mode) +{ + GLenum gl_mode; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (mode == ctx->matrix_mode) + return; + ctx->matrix_mode = mode; + + gl_mode = 0; /* silence compiler warning */ + switch (mode) + { + case COGL_MATRIX_MODELVIEW: + gl_mode = GL_MODELVIEW; + break; + case COGL_MATRIX_PROJECTION: + gl_mode = GL_PROJECTION; + break; + case COGL_MATRIX_TEXTURE: + gl_mode = GL_TEXTURE; + break; + } + + GE (glMatrixMode (gl_mode)); +} + +static void +_cogl_get_client_stack (CoglContext *ctx, + CoglMatrixStack **current_stack_p) +{ + if (ctx->modelview_stack && + ctx->matrix_mode == COGL_MATRIX_MODELVIEW) + *current_stack_p = ctx->modelview_stack; + else + *current_stack_p = NULL; +} + +#define _COGL_GET_CONTEXT_AND_STACK(contextvar, stackvar, rval) \ + CoglMatrixStack *stackvar; \ + _COGL_GET_CONTEXT (contextvar, rval); \ + _cogl_get_client_stack (contextvar, &stackvar) + +void +_cogl_current_matrix_push (void) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_push (current_stack); + else + GE (glPushMatrix ()); +} + +void +_cogl_current_matrix_pop (void) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_pop (current_stack); + else + GE (glPopMatrix ()); +} + +void +_cogl_current_matrix_identity (void) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_load_identity (current_stack); + else + GE (glLoadIdentity ()); +} + +void +_cogl_current_matrix_load (const CoglMatrix *matrix) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_set (current_stack, matrix); + else + GE (glLoadMatrixf (cogl_matrix_get_array (matrix))); +} + +void +_cogl_current_matrix_multiply (const CoglMatrix *matrix) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_multiply (current_stack, matrix); + else + GE (glMultMatrixf (cogl_matrix_get_array (matrix))); +} + +void +_cogl_current_matrix_rotate (float angle, + float x, + float y, + float z) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_rotate (current_stack, angle, x, y, z); + else + GE (glRotatef (angle, x, y, z)); +} + +void +_cogl_current_matrix_scale (float x, + float y, + float z) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_scale (current_stack, x, y, z); + else + GE (glScalef (x, y, z)); +} + +void +_cogl_current_matrix_translate (float x, + float y, + float z) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_translate (current_stack, x, y, z); + else + GE (glTranslatef (x, y, z)); +} + +void +_cogl_current_matrix_frustum (float left, + float right, + float bottom, + float top, + float near_val, + float far_val) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_frustum (current_stack, + left, right, + top, bottom, + near_val, + far_val); + else + GE (glFrustum (left, right, bottom, top, near_val, far_val)); +} + +void +_cogl_current_matrix_ortho (float left, + float right, + float bottom, + float top, + float near_val, + float far_val) +{ +#if 0 + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_ortho (current_stack, + left, right, + top, bottom, + near_val, + far_val); + else + GE (glOrtho (left, right, bottom, top, near_val, far_val)); +#else + /* Nobody is using glOrtho right now anyway, so not bothering */ + g_warning ("%s not implemented, need to code cogl_matrix_ortho() if you need this function", + G_STRFUNC); +#endif +} + +void +_cogl_get_matrix (CoglMatrixMode mode, + CoglMatrix *matrix) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->modelview_stack != NULL && + mode == COGL_MATRIX_MODELVIEW) + { + _cogl_matrix_stack_get (ctx->modelview_stack, matrix); + } + else + { + GLenum gl_mode; + + gl_mode = 0; /* silence compiler warning */ + switch (mode) + { + case COGL_MATRIX_MODELVIEW: + gl_mode = GL_MODELVIEW_MATRIX; + break; + case COGL_MATRIX_PROJECTION: + gl_mode = GL_PROJECTION_MATRIX; + break; + case COGL_MATRIX_TEXTURE: + gl_mode = GL_TEXTURE_MATRIX; + break; + } + + /* hack alert: CoglMatrix is not really expecting us to + * get *mutable* floats array from it + */ + GE (glGetFloatv (gl_mode, (GLfloat*) matrix)); + } +} + +void +_cogl_current_matrix_state_init (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + ctx->matrix_mode = COGL_MATRIX_MODELVIEW; + ctx->modelview_stack = NULL; + + if (ctx->indirect) + { + ctx->modelview_stack = + _cogl_matrix_stack_new (); + } +} + +void +_cogl_current_matrix_state_destroy (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->modelview_stack) + _cogl_matrix_stack_destroy (ctx->modelview_stack); +} + +void +_cogl_current_matrix_state_flush (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->matrix_mode != COGL_MATRIX_MODELVIEW) + { + g_warning ("matrix state must be flushed in MODELVIEW mode"); + return; + } + + if (ctx->modelview_stack) + { + _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack, + GL_MODELVIEW); + } +} + +void +cogl_push_matrix (void) +{ + _cogl_current_matrix_push (); +} + +void +cogl_pop_matrix (void) +{ + _cogl_current_matrix_pop (); +} + +void +cogl_scale (float x, float y, float z) +{ + _cogl_current_matrix_scale (x, y, z); +} + +void +cogl_translate (float x, float y, float z) +{ + _cogl_current_matrix_translate (x, y, z); +} + +void +cogl_rotate (float angle, float x, float y, float z) +{ + _cogl_current_matrix_rotate (angle, x, y, z); +} + +void +_cogl_set_matrix (const CoglMatrix *matrix) +{ + _cogl_current_matrix_load (matrix); +} + +void +cogl_get_modelview_matrix (CoglMatrix *matrix) +{ + _cogl_get_matrix (COGL_MATRIX_MODELVIEW, + matrix); +} + +void +cogl_get_projection_matrix (CoglMatrix *matrix) +{ + _cogl_get_matrix (COGL_MATRIX_PROJECTION, + matrix); +} + +void +cogl_perspective (float fovy, + float aspect, + float zNear, + float zFar) +{ + float xmax, ymax; + float x, y, c, d; + float fovy_rad_half = (fovy * G_PI) / 360; + CoglMatrix perspective; + GLfloat m[16]; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + memset (&m[0], 0, sizeof (m)); + + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_identity (); + + /* + * Based on the original algorithm in perspective(): + * + * 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax + * same true for y, hence: a == 0 && b == 0; + * + * 2) When working with small numbers, we are loosing significant + * precision + */ + ymax = (zNear * (sinf (fovy_rad_half) / cosf (fovy_rad_half))); + xmax = (ymax * aspect); + + x = (zNear / xmax); + y = (zNear / ymax); + c = (-(zFar + zNear) / ( zFar - zNear)); + d = (-(2 * zFar) * zNear) / (zFar - zNear); + +#define M(row,col) m[col*4+row] + M(0,0) = x; + M(1,1) = y; + M(2,2) = c; + M(2,3) = d; + M(3,2) = -1.0; + + cogl_matrix_init_from_array (&perspective, m); + _cogl_current_matrix_multiply (&perspective); + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + + /* Calculate and store the inverse of the matrix */ + memset (ctx->inverse_projection, 0, sizeof (float) * 16); + +#define m ctx->inverse_projection + M(0, 0) = (1.0 / x); + M(1, 1) = (1.0 / y); + M(2, 3) = -1.0; + M(3, 2) = (1.0 / d); + M(3, 3) = (c / d); +#undef m + +#undef M +} + +void +cogl_frustum (float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + float c, d; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_identity (); + + _cogl_current_matrix_frustum (left, + right, + bottom, + top, + z_near, + z_far); + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + + /* Calculate and store the inverse of the matrix */ + memset (ctx->inverse_projection, 0, sizeof (float) * 16); + + c = - (z_far + z_near) / (z_far - z_near); + d = - (2 * (z_far * z_near)) / (z_far - z_near); + +#define M(row,col) ctx->inverse_projection[col*4+row] + M(0,0) = (right - left) / (2 * z_near); + M(0,3) = (right + left) / (2 * z_near); + M(1,1) = (top - bottom) / (2 * z_near); + M(1,3) = (top + bottom) / (2 * z_near); + M(2,3) = -1.0; + M(3,2) = 1.0 / d; + M(3,3) = c / d; +#undef M +} diff --git a/clutter/cogl/common/cogl-current-matrix.h b/clutter/cogl/common/cogl-current-matrix.h new file mode 100644 index 000000000..3e271c97a --- /dev/null +++ b/clutter/cogl/common/cogl-current-matrix.h @@ -0,0 +1,91 @@ +/* + * Clutter COGL + * + * A basic GL/GLES Abstraction/Utility Layer + * + * Authored By Havoc Pennington for litl + * + * Copyright (C) 2009 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __COGL_CURRENT_MATRIX_H +#define __COGL_CURRENT_MATRIX_H + +#include + +/** + * CoglMatrixMode: + * @COGL_MATRIX_MODELVIEW: Select model-view matrix stack + * @COGL_MATRIX_PROJECTION: Select projection matrix stack + * @COGL_MATRIX_TEXTURE: Select texture matrix stack + * + * There are several matrix stacks affected by the COGL current matrix + * operations (which are private). Code should always leave the + * model-view matrix active, switching to the projection matrix stack + * only temporarily in order to modify the projection matrix. Most + * COGL and Clutter APIs (other than the current matrix operations) + * will assume the model-view matrix is active when the API is + * invoked. + * + * Since: 1.0 + */ +typedef enum +{ + COGL_MATRIX_MODELVIEW = 1, + COGL_MATRIX_PROJECTION = 2, + COGL_MATRIX_TEXTURE = 3 +} CoglMatrixMode; + +#define COGL_TYPE_MATRIX_MODE (cogl_matrix_mode_get_type ()) +GType cogl_matrix_mode_get_type (void) G_GNUC_CONST; + +void _cogl_set_current_matrix (CoglMatrixMode mode); +void _cogl_current_matrix_push (void); +void _cogl_current_matrix_pop (void); +void _cogl_current_matrix_identity (void); +void _cogl_current_matrix_load (const CoglMatrix *matrix); +void _cogl_current_matrix_multiply (const CoglMatrix *matrix); +void _cogl_current_matrix_rotate (float angle, + float x, + float y, + float z); +void _cogl_current_matrix_scale (float x, + float y, + float z); +void _cogl_current_matrix_translate (float x, + float y, + float z); +void _cogl_current_matrix_frustum (float left, + float right, + float bottom, + float top, + float near_val, + float far_val); +void _cogl_current_matrix_ortho (float left, + float right, + float bottom, + float top, + float near_val, + float far_val); +void _cogl_get_matrix (CoglMatrixMode mode, + CoglMatrix *matrix); +void _cogl_current_matrix_state_init (void); +void _cogl_current_matrix_state_destroy (void); +void _cogl_current_matrix_state_flush (void); + +#endif /* __COGL_CURRENT_MATRIX_H */ diff --git a/clutter/cogl/common/cogl-material.c b/clutter/cogl/common/cogl-material.c index 7ee64196e..47fdc81d8 100644 --- a/clutter/cogl/common/cogl-material.c +++ b/clutter/cogl/common/cogl-material.c @@ -821,9 +821,9 @@ _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer, layer->flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX)) #endif { - GE (glMatrixMode (GL_TEXTURE)); - GE (glLoadMatrixf ((GLfloat *)&layer->matrix)); - GE (glMatrixMode (GL_MODELVIEW)); + _cogl_set_current_matrix (COGL_MATRIX_TEXTURE); + _cogl_current_matrix_load (&layer->matrix); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); } } diff --git a/clutter/cogl/common/cogl-matrix-stack.c b/clutter/cogl/common/cogl-matrix-stack.c new file mode 100644 index 000000000..38429fc6c --- /dev/null +++ b/clutter/cogl/common/cogl-matrix-stack.c @@ -0,0 +1,327 @@ +/* + * Clutter COGL + * + * A basic GL/GLES Abstraction/Utility Layer + * + * Authored By Havoc Pennington for litl + * + * Copyright (C) 2009 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "cogl.h" +#include "cogl-context.h" +#include "cogl-internal.h" +#include "cogl-matrix-stack.h" + +typedef struct { + CoglMatrix matrix; + /* count of pushes with no changes; when a change is + * requested, we create a new state and decrement this + */ + int push_count; +} CoglMatrixState; + +/** + * CoglMatrixStack: + * + * Stores a cogl-side matrix stack, which we use as a cache + * so we can get the matrix efficiently when using indirect + * rendering. + */ +struct _CoglMatrixStack +{ + GSList *stack; + + /* which state does GL have, NULL if unknown */ + CoglMatrixState *flushed_state; +}; + + +static CoglMatrixState* +_cogl_matrix_state_new (void) +{ + CoglMatrixState *state; + + state = g_slice_new0 (CoglMatrixState); + + /* load identity */ + cogl_matrix_init_identity (&state->matrix); + + /* state->push_count defaults to 0 */ + + return state; +} + +static void +_cogl_matrix_state_destroy (CoglMatrixState *state) +{ + + g_slice_free (CoglMatrixState, state); +} + +static CoglMatrixState* +_cogl_matrix_stack_top (CoglMatrixStack *stack) +{ + return stack->stack->data; +} + +static CoglMatrixState* +_cogl_matrix_stack_top_mutable (CoglMatrixStack *stack) +{ + CoglMatrixState *state; + CoglMatrixState *new_top; + + state = _cogl_matrix_stack_top (stack); + + if (state->push_count == 0) + return state; + + state->push_count -= 1; + + new_top = _cogl_matrix_state_new (); + + new_top->matrix = state->matrix; + + if (stack->flushed_state == state) + { + stack->flushed_state = new_top; + } + + stack->stack = + g_slist_prepend (stack->stack, + new_top); + + return new_top; +} + +CoglMatrixStack* +_cogl_matrix_stack_new (void) +{ + CoglMatrixStack *stack; + CoglMatrixState *state; + + stack = g_slice_new0 (CoglMatrixStack); + state = _cogl_matrix_state_new (); + stack->stack = + g_slist_prepend (stack->stack, + state); + + return stack; +} + +void +_cogl_matrix_stack_destroy (CoglMatrixStack *stack) +{ + while (stack->stack) + { + CoglMatrixState *state; + + state = stack->stack->data; + _cogl_matrix_state_destroy (state); + stack->stack = + g_slist_delete_link (stack->stack, + stack->stack); + } + + g_slice_free (CoglMatrixStack, stack); +} + +void +_cogl_matrix_stack_push (CoglMatrixStack *stack) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top (stack); + + /* we lazily create a new stack top if someone changes the matrix + * while push_count > 0 + */ + state->push_count += 1; +} + +void +_cogl_matrix_stack_pop (CoglMatrixStack *stack) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top (stack); + + if (state->push_count > 0) + { + state->push_count -= 1; + } + else + { + if (stack->stack->next == NULL) + { + g_warning ("Too many matrix pops"); + return; + } + + if (stack->flushed_state == state) + { + stack->flushed_state = NULL; + } + + stack->stack = + g_slist_delete_link (stack->stack, + stack->stack); + _cogl_matrix_state_destroy (state); + } +} + +void +_cogl_matrix_stack_load_identity (CoglMatrixStack *stack) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_init_identity (&state->matrix); + + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_scale (CoglMatrixStack *stack, + float x, + float y, + float z) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_scale (&state->matrix, x, y, z); + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_translate (CoglMatrixStack *stack, + float x, + float y, + float z) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_translate (&state->matrix, x, y, z); + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_rotate (CoglMatrixStack *stack, + float angle, + float x, + float y, + float z) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_rotate (&state->matrix, angle, x, y, z); + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_multiply (CoglMatrixStack *stack, + const CoglMatrix *matrix) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_multiply (&state->matrix, &state->matrix, matrix); + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_get (CoglMatrixStack *stack, + CoglMatrix *matrix) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top (stack); + + *matrix = state->matrix; +} + +void +_cogl_matrix_stack_set (CoglMatrixStack *stack, + const CoglMatrix *matrix) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + state->matrix = *matrix; + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_frustum (CoglMatrixStack *stack, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_frustum (&state->matrix, + left, right, bottom, top, + z_near, z_far); + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, + GLenum gl_mode) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top (stack); + + if (stack->flushed_state == state) + return; + + /* NOTE we assume caller was in MODELVIEW mode */ + + if (gl_mode != GL_MODELVIEW) + GE (glMatrixMode (gl_mode)); + + /* In theory it might help the GL implementation if we used our + * local analysis of the matrix and called Translate/Scale rather + * than LoadMatrix to send a 2D matrix + */ + + GE (glLoadMatrixf (cogl_matrix_get_array (&state->matrix))); + stack->flushed_state = state; + + if (gl_mode != GL_MODELVIEW) + GE (glMatrixMode (GL_MODELVIEW)); +} diff --git a/clutter/cogl/common/cogl-matrix-stack.h b/clutter/cogl/common/cogl-matrix-stack.h new file mode 100644 index 000000000..9f8001692 --- /dev/null +++ b/clutter/cogl/common/cogl-matrix-stack.h @@ -0,0 +1,67 @@ +/* + * Clutter COGL + * + * A basic GL/GLES Abstraction/Utility Layer + * + * Authored By Havoc Pennington for litl + * + * Copyright (C) 2009 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __COGL_MATRIX_STACK_H +#define __COGL_MATRIX_STACK_H + +#include + +typedef struct _CoglMatrixStack CoglMatrixStack; + +CoglMatrixStack* _cogl_matrix_stack_new (void); +void _cogl_matrix_stack_destroy (CoglMatrixStack *stack); +void _cogl_matrix_stack_push (CoglMatrixStack *stack); +void _cogl_matrix_stack_pop (CoglMatrixStack *stack); +void _cogl_matrix_stack_load_identity (CoglMatrixStack *stack); +void _cogl_matrix_stack_scale (CoglMatrixStack *stack, + float x, + float y, + float z); +void _cogl_matrix_stack_translate (CoglMatrixStack *stack, + float x, + float y, + float z); +void _cogl_matrix_stack_rotate (CoglMatrixStack *stack, + float angle, + float x, + float y, + float z); +void _cogl_matrix_stack_multiply (CoglMatrixStack *stack, + const CoglMatrix *matrix); +void _cogl_matrix_stack_get (CoglMatrixStack *stack, + CoglMatrix *matrix); +void _cogl_matrix_stack_set (CoglMatrixStack *stack, + const CoglMatrix *matrix); +void _cogl_matrix_stack_frustum (CoglMatrixStack *stack, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far); +void _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, + GLenum gl_mode); + +#endif /* __COGL_MATRIX_STACK_H */ diff --git a/clutter/cogl/common/cogl-matrix.c b/clutter/cogl/common/cogl-matrix.c index a99473da9..0a041e7e3 100644 --- a/clutter/cogl/common/cogl-matrix.c +++ b/clutter/cogl/common/cogl-matrix.c @@ -140,6 +140,48 @@ cogl_matrix_transform_point (const CoglMatrix *matrix, *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w; } +void +cogl_matrix_frustum (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + float x, y, a, b, c, d; + CoglMatrix frustum; + + x = (2.0f * z_near) / (right - left); + y = (2.0f * z_near) / (top - bottom); + a = (right + left) / (right - left); + b = (top + bottom) / (top - bottom); + c = -(z_far + z_near) / ( z_far - z_near); + d = -(2.0f * z_far* z_near) / (z_far - z_near); + + frustum.xx = x; + frustum.yx = 0.0f; + frustum.zx = 0.0f; + frustum.wx = 0.0f; + + frustum.xy = 0.0f; + frustum.yy = y; + frustum.zy = 0.0f; + frustum.wy = 0.0f; + + frustum.xz = a; + frustum.yz = b; + frustum.zz = c; + frustum.wz = -1.0f; + + frustum.xw = 0.0f; + frustum.yw = 0.0f; + frustum.zw = d; + frustum.ww = 0.0f; + + cogl_matrix_multiply (matrix, matrix, &frustum); +} + void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array) { diff --git a/clutter/cogl/common/cogl-util.c b/clutter/cogl/common/cogl-util.c index f96a82bef..640d90801 100644 --- a/clutter/cogl/common/cogl-util.c +++ b/clutter/cogl/common/cogl-util.c @@ -35,6 +35,7 @@ #include "cogl-fixed.h" #include "cogl-internal.h" #include "cogl-material.h" +#include "cogl-current-matrix.h" #include "cogl-offscreen.h" #include "cogl-shader.h" #include "cogl-texture.h" @@ -208,6 +209,28 @@ cogl_buffer_target_get_type (void) return gtype; } +GType +cogl_matrix_mode_get_type (void) +{ + static GType gtype = 0; + + if (G_UNLIKELY (gtype == 0)) + { + static const GEnumValue values[] = { + { COGL_MATRIX_MODELVIEW, "COGL_MATRIX_MODELVIEW", "modelview" }, + { COGL_MATRIX_PROJECTION, "COGL_MATRIX_PROJECTION", "projection" }, + { COGL_MATRIX_TEXTURE, "COGL_MATRIX_TEXTURE", "texture" }, + { 0, NULL, NULL } + }; + + gtype = + g_enum_register_static (g_intern_static_string ("CoglMatrixMode"), + values); + } + + return gtype; +} + GType cogl_texture_flags_get_type (void) { diff --git a/clutter/cogl/common/cogl-vertex-buffer.c b/clutter/cogl/common/cogl-vertex-buffer.c index 758828412..125d9e675 100644 --- a/clutter/cogl/common/cogl-vertex-buffer.c +++ b/clutter/cogl/common/cogl-vertex-buffer.c @@ -1621,6 +1621,8 @@ cogl_vertex_buffer_draw (CoglHandle handle, enable_state_for_drawing_buffer (buffer); + _cogl_current_matrix_state_flush (); + /* FIXME: flush cogl cache */ GE (glDrawArrays (mode, first, count)); @@ -1647,6 +1649,8 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle, enable_state_for_drawing_buffer (buffer); + _cogl_current_matrix_state_flush (); + /* FIXME: flush cogl cache */ GE (glDrawRangeElements (mode, min_index, max_index, count, indices_type, indices)); diff --git a/clutter/cogl/gl/cogl-context.c b/clutter/cogl/gl/cogl-context.c index 2ff8aa856..777484d12 100644 --- a/clutter/cogl/gl/cogl-context.c +++ b/clutter/cogl/gl/cogl-context.c @@ -37,6 +37,7 @@ #include static CoglContext *_context = NULL; +static gboolean gl_is_indirect = FALSE; gboolean cogl_create_context () @@ -59,6 +60,8 @@ cogl_create_context () _context->enable_backface_culling = FALSE; + _context->indirect = gl_is_indirect; + _context->material_handles = NULL; _context->material_layer_handles = NULL; _context->default_material = cogl_material_new (); @@ -143,6 +146,9 @@ cogl_create_context () /* Initialise the clip stack */ _cogl_clip_stack_state_init (); + /* Initialise matrix stack */ + _cogl_current_matrix_state_init (); + /* Create default textures used for fall backs */ _context->default_gl_texture_2d_tex = cogl_texture_new_from_data (1, /* width */ @@ -182,6 +188,8 @@ cogl_destroy_context () _cogl_clip_stack_state_destroy (); + _cogl_current_matrix_state_destroy (); + if (_context->path_nodes) g_array_free (_context->path_nodes, TRUE); @@ -226,3 +234,32 @@ _cogl_context_get_default () return _context; } + +/** + * _cogl_set_indirect_context: + * @indirect: TRUE if GL context is indirect + * + * Advises COGL that the GL context is indirect (commands are sent + * over a socket). COGL uses this information to try to avoid + * round-trips in its use of GL, for example. + * + * This function cannot be called "on the fly," only before COGL + * initializes. + */ +void +_cogl_set_indirect_context (gboolean indirect) +{ + /* we get called multiple times if someone creates + * more than the default stage + */ + if (_context != NULL) + { + if (indirect != _context->indirect) + g_warning ("Right now all stages will be treated as " + "either direct or indirect, ignoring attempt " + "to change to indirect=%d", indirect); + return; + } + + gl_is_indirect = indirect; +} diff --git a/clutter/cogl/gl/cogl-context.h b/clutter/cogl/gl/cogl-context.h index bcffdfa19..14de41c3c 100644 --- a/clutter/cogl/gl/cogl-context.h +++ b/clutter/cogl/gl/cogl-context.h @@ -28,6 +28,8 @@ #include "cogl-primitives.h" #include "cogl-clip-stack.h" +#include "cogl-matrix-stack.h" +#include "cogl-current-matrix.h" typedef struct { @@ -48,6 +50,12 @@ typedef struct gboolean enable_backface_culling; + gboolean indirect; + + /* Client-side matrix stack or NULL if none */ + CoglMatrixMode matrix_mode; + CoglMatrixStack *modelview_stack; + /* Cache of inverse projection matrix */ float inverse_projection[16]; diff --git a/clutter/cogl/gl/cogl-fbo.c b/clutter/cogl/gl/cogl-fbo.c index 3275f4df9..42a28a44c 100644 --- a/clutter/cogl/gl/cogl-fbo.c +++ b/clutter/cogl/gl/cogl-fbo.c @@ -264,30 +264,30 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen) /* Push the viewport and matrix setup if redirecting from a non-screen buffer */ GE( glPushAttrib (GL_VIEWPORT_BIT) ); - - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); - - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); } else { /* Override viewport and matrix setup if redirecting from another offscreen buffer */ - GE( glMatrixMode (GL_PROJECTION) ); - GE( glLoadIdentity () ); - - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glLoadIdentity () ); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_identity (); + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_identity (); } /* Setup new viewport and matrices */ GE( glViewport (0, 0, fbo->width, fbo->height) ); - GE( glTranslatef (-1.0f, -1.0f, 0.0f) ); - GE( glScalef (2.0f / fbo->width, 2.0f / fbo->height, 1.0f) ); + _cogl_current_matrix_translate (-1.0f, -1.0f, 0.0f); + _cogl_current_matrix_scale (2.0f / fbo->width, 2.0f / fbo->height, 1.0f); /* Bind offscreen framebuffer object */ GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo->gl_handle) ); @@ -313,12 +313,12 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen) /* Pop viewport and matrices if redirecting back from an offscreen buffer */ GE( glPopAttrib () ); - - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPopMatrix () ); - - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPopMatrix () ); + + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_pop (); + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_pop (); } /* Bind window framebuffer object */ diff --git a/clutter/cogl/gl/cogl-primitives.c b/clutter/cogl/gl/cogl-primitives.c index 917e69840..07e728beb 100644 --- a/clutter/cogl/gl/cogl-primitives.c +++ b/clutter/cogl/gl/cogl-primitives.c @@ -87,6 +87,7 @@ _cogl_path_stroke_nodes () COGL_MATERIAL_FLUSH_DISABLE_MASK, (guint32)~0, /* disable all texture layers */ NULL); + _cogl_current_matrix_state_flush (); while (path_start < ctx->path_nodes->len) { @@ -161,6 +162,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, GE( glColorMask (FALSE, FALSE, FALSE, FALSE) ); GE( glDepthMask (FALSE) ); + _cogl_current_matrix_state_flush (); while (path_start < path_size) { GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode), @@ -196,16 +198,18 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) ); /* Decrement all of the bits twice so that only pixels where the value is 3 will remain */ - GE( glPushMatrix () ); - GE( glLoadIdentity () ); - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); + + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); cogl_rectangle (-1.0, -1.0, 1.0, 1.0); cogl_rectangle (-1.0, -1.0, 1.0, 1.0); - GE( glPopMatrix () ); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPopMatrix () ); + _cogl_current_matrix_pop (); + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_pop (); } GE( glStencilMask (~(GLuint) 0) ); diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index 0d5358cae..51d3ebf61 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -2056,7 +2056,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, cogl_enable (enable_flags); GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer)); - + _cogl_current_matrix_state_flush (); GE (glDrawRangeElements (GL_TRIANGLES, 0, ctx->static_indices->len - 1, 6 * batch_len, @@ -2085,6 +2085,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, color == 2 ? 0xff : 0x00, 0xff); cogl_material_flush_gl_state (outline, NULL); + _cogl_current_matrix_state_flush (); GE( glDrawArrays (GL_LINE_LOOP, 4 * i, 4) ); } } @@ -2896,6 +2897,7 @@ _cogl_texture_sliced_polygon (CoglTextureVertex *vertices, COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, gl_handle, NULL); + _cogl_current_matrix_state_flush (); GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) ); } @@ -2986,6 +2988,7 @@ _cogl_multitexture_unsliced_polygon (CoglTextureVertex *vertices, COGL_MATERIAL_FLUSH_FALLBACK_MASK, fallback_mask, NULL); + _cogl_current_matrix_state_flush (); GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices)); } diff --git a/clutter/cogl/gl/cogl.c b/clutter/cogl/gl/cogl.c index 3443f7121..5f7f04833 100644 --- a/clutter/cogl/gl/cogl.c +++ b/clutter/cogl/gl/cogl.c @@ -201,37 +201,6 @@ cogl_clear (const CoglColor *color) */ } -/* FIXME: inline most of these */ -void -cogl_push_matrix (void) -{ - GE( glPushMatrix() ); -} - -void -cogl_pop_matrix (void) -{ - GE( glPopMatrix() ); -} - -void -cogl_scale (float x, float y, float z) -{ - GE( glScalef (x, y, z) ); -} - -void -cogl_translate (float x, float y, float z) -{ - GE( glTranslatef (x, y, z) ); -} - -void -cogl_rotate (float angle, float x, float y, float z) -{ - GE( glRotatef (angle, x, y, z) ); -} - static inline gboolean cogl_toggle_flag (CoglContext *ctx, gulong new_flags, @@ -396,6 +365,7 @@ set_clip_plane (GLint plane_num, GLdouble plane[4]; #endif GLfloat angle; + CoglMatrix inverse_projection; _COGL_GET_CONTEXT (ctx, NO_RETVAL); /* Calculate the angle between the axes and the line crossing the @@ -403,18 +373,20 @@ set_clip_plane (GLint plane_num, angle = atan2f (vertex_b[1] - vertex_a[1], vertex_b[0] - vertex_a[0]) * (180.0/G_PI); - GE( glPushMatrix () ); + _cogl_current_matrix_push (); /* Load the identity matrix and multiply by the reverse of the projection matrix so we can specify the plane in screen coordinates */ - GE( glLoadIdentity () ); - GE( glMultMatrixf ((GLfloat *) ctx->inverse_projection) ); + _cogl_current_matrix_identity (); + cogl_matrix_init_from_array (&inverse_projection, + ctx->inverse_projection); + _cogl_current_matrix_multiply (&inverse_projection); /* Rotate about point a */ - GE( glTranslatef (vertex_a[0], vertex_a[1], vertex_a[2]) ); + _cogl_current_matrix_translate (vertex_a[0], vertex_a[1], vertex_a[2]); /* Rotate the plane by the calculated angle so that it will connect the two points */ - GE( glRotatef (angle, 0.0f, 0.0f, 1.0f) ); - GE( glTranslatef (-vertex_a[0], -vertex_a[1], -vertex_a[2]) ); + _cogl_current_matrix_rotate (angle, 0.0f, 0.0f, 1.0f); + _cogl_current_matrix_translate (-vertex_a[0], -vertex_a[1], -vertex_a[2]); plane[0] = 0; plane[1] = -1.0; @@ -426,7 +398,7 @@ set_clip_plane (GLint plane_num, GE( glClipPlane (plane_num, plane) ); #endif - GE( glPopMatrix () ); + _cogl_current_matrix_pop (); } void @@ -435,7 +407,10 @@ _cogl_set_clip_planes (float x_offset, float width, float height) { - GLfloat modelview[16], projection[16]; + CoglMatrix modelview_matrix; + CoglMatrix projection_matrix; + GLfloat *modelview; + GLfloat *projection; float vertex_tl[4] = { x_offset, y_offset, 0, 1.0 }; float vertex_tr[4] = { x_offset + width, y_offset, 0, 1.0 }; @@ -443,8 +418,18 @@ _cogl_set_clip_planes (float x_offset, float vertex_br[4] = { x_offset + width, y_offset + height, 0, 1.0 }; - GE( glGetFloatv (GL_MODELVIEW_MATRIX, modelview) ); - GE( glGetFloatv (GL_PROJECTION_MATRIX, projection) ); + /* hack alert: there's no way to get *and modify* + * CoglMatrix as a float array. So we just + * use a cast instead of cogl_matrix_get_array(), + * and know that we will not call any more CoglMatrix + * methods after we write to it directly. + */ + _cogl_get_matrix (COGL_MATRIX_PROJECTION, + &projection_matrix); + projection = (GLfloat*) &projection_matrix; + _cogl_get_matrix (COGL_MATRIX_MODELVIEW, + &modelview_matrix); + modelview = (GLfloat*) &modelview_matrix; project_vertex (modelview, projection, vertex_tl); project_vertex (modelview, projection, vertex_tr); @@ -513,15 +498,15 @@ _cogl_add_stencil_clip (float x_offset, only pixels where both the original stencil buffer and the rectangle are set will be valid */ GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); cogl_rectangle (-1.0, -1.0, 1.0, 1.0); - GE( glPopMatrix () ); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPopMatrix () ); + _cogl_current_matrix_pop (); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_pop (); } /* Restore the stencil mode */ @@ -529,14 +514,6 @@ _cogl_add_stencil_clip (float x_offset, GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) ); } -void -_cogl_set_matrix (const CoglMatrix *matrix) -{ - const GLfloat *gl_matrix = cogl_matrix_get_array (matrix); - - GE (glLoadMatrixf (gl_matrix)); -} - void _cogl_disable_stencil_buffer (void) { @@ -561,108 +538,6 @@ _cogl_disable_clip_planes (void) GE( glDisable (GL_CLIP_PLANE0) ); } -void -cogl_perspective (float fovy, - float aspect, - float zNear, - float zFar) -{ - float xmax, ymax; - float x, y, c, d; - float fovy_rad_half = (fovy * G_PI) / 360; - - GLfloat m[16]; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - memset (&m[0], 0, sizeof (m)); - - GE( glMatrixMode (GL_PROJECTION) ); - GE( glLoadIdentity () ); - - /* - * Based on the original algorithm in perspective(): - * - * 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax - * same true for y, hence: a == 0 && b == 0; - * - * 2) When working with small numbers, we are loosing significant - * precision - */ - ymax = (zNear * (sinf (fovy_rad_half) / cosf (fovy_rad_half))); - xmax = (ymax * aspect); - - x = (zNear / xmax); - y = (zNear / ymax); - c = (-(zFar + zNear) / ( zFar - zNear)); - d = (-(2 * zFar) * zNear) / (zFar - zNear); - -#define M(row,col) m[col*4+row] - M(0,0) = x; - M(1,1) = y; - M(2,2) = c; - M(2,3) = d; - M(3,2) = -1.0; - - GE( glMultMatrixf (m) ); - - GE( glMatrixMode (GL_MODELVIEW) ); - - /* Calculate and store the inverse of the matrix */ - memset (ctx->inverse_projection, 0, sizeof (float) * 16); - -#define m ctx->inverse_projection - M(0, 0) = (1.0 / x); - M(1, 1) = (1.0 / y); - M(2, 3) = -1.0; - M(3, 2) = (1.0 / d); - M(3, 3) = (c / d); -#undef m - -#undef M -} - -void -cogl_frustum (float left, - float right, - float bottom, - float top, - float z_near, - float z_far) -{ - float c, d; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - GE( glMatrixMode (GL_PROJECTION) ); - GE( glLoadIdentity () ); - - GE( glFrustum ((GLdouble)(left), - (GLdouble)(right), - (GLdouble)(bottom), - (GLdouble)(top), - (GLdouble)(z_near), - (GLdouble)(z_far)) ); - - GE( glMatrixMode (GL_MODELVIEW) ); - - /* Calculate and store the inverse of the matrix */ - memset (ctx->inverse_projection, 0, sizeof (float) * 16); - - c = - (z_far + z_near) / (z_far - z_near); - d = - (2 * (z_far * z_near)) / (z_far - z_near); - -#define M(row,col) ctx->inverse_projection[col*4+row] - M(0,0) = (right - left) / (2 * z_near); - M(0,3) = (right + left) / (2 * z_near); - M(1,1) = (top - bottom) / (2 * z_near); - M(1,3) = (top + bottom) / (2 * z_near); - M(2,3) = -1.0; - M(3,2) = 1.0 / d; - M(3,3) = c / d; -#undef M -} - void cogl_viewport (guint width, guint height) @@ -684,8 +559,8 @@ cogl_setup_viewport (guint width, GE( glViewport (0, 0, width, height) ); /* For Ortho projection. - * glOrthof (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); - */ + * _cogl_current_matrix_ortho (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); + */ cogl_perspective (fovy, aspect, z_near, z_far); @@ -731,11 +606,10 @@ cogl_setup_viewport (guint width, cogl_get_projection_matrix (&projection_matrix); z_camera = 0.5 * projection_matrix.xx; - GE( glLoadIdentity () ); - - GE( glTranslatef (-0.5f, -0.5f, -z_camera) ); - GE( glScalef (1.0f / width, -1.0f / height, 1.0f / width) ); - GE( glTranslatef (0.0f, -1.0 * height, 0.0f) ); + _cogl_current_matrix_identity (); + _cogl_current_matrix_translate (-0.5f, -0.5f, -z_camera); + _cogl_current_matrix_scale (1.0f / width, -1.0f / height, 1.0f / width); + _cogl_current_matrix_translate (0.0f, -1.0 * height, 0.0f); } #ifdef HAVE_CLUTTER_OSX @@ -1122,28 +996,6 @@ cogl_features_available (CoglFeatureFlags features) return (ctx->feature_flags & features) == features; } -void -cogl_get_modelview_matrix (CoglMatrix *matrix) -{ - float m[16]; - glGetFloatv (GL_MODELVIEW_MATRIX, m); - /* Since it's internal to Cogl and CoglMatrix doesn't currently have - * any flag members, we could avoid this extra copy if it really - * bothers anyone */ - cogl_matrix_init_from_array (matrix, m); -} - -void -cogl_get_projection_matrix (CoglMatrix *matrix) -{ - float m[16]; - glGetFloatv (GL_PROJECTION_MATRIX, m); - /* Since it's internal to Cogl and CoglMatrix doesn't currently have - * any flag members, we could avoid this extra copy if it really - * bothers anyone */ - cogl_matrix_init_from_array (matrix, m); -} - void cogl_get_viewport (float v[4]) { @@ -1234,3 +1086,8 @@ cogl_disable_fog (void) glDisable (GL_FOG); } +void +cogl_flush_gl_state (int flags) +{ + _cogl_current_matrix_state_flush (); +} diff --git a/clutter/cogl/gles/cogl-context.c b/clutter/cogl/gles/cogl-context.c index 0f8592440..03bd2aaea 100644 --- a/clutter/cogl/gles/cogl-context.c +++ b/clutter/cogl/gles/cogl-context.c @@ -39,6 +39,7 @@ #include static CoglContext *_context = NULL; +static gboolean gl_is_indirect = FALSE; gboolean cogl_create_context () @@ -61,6 +62,8 @@ cogl_create_context () _context->enable_backface_culling = FALSE; + _context->indirect = gl_is_indirect; + _context->material_handles = NULL; _context->material_layer_handles = NULL; _context->default_material = cogl_material_new (); @@ -104,6 +107,9 @@ cogl_create_context () /* Initialise the clip stack */ _cogl_clip_stack_state_init (); + /* Initialise matrix stack */ + _cogl_current_matrix_state_init (); + /* Create default textures used for fall backs */ _context->default_gl_texture_2d_tex = cogl_texture_new_from_data (1, /* width */ @@ -143,6 +149,8 @@ cogl_destroy_context () _cogl_clip_stack_state_destroy (); + _cogl_current_matrix_state_destroy (); + if (_context->path_nodes) g_array_free (_context->path_nodes, TRUE); @@ -187,3 +195,32 @@ _cogl_context_get_default () return _context; } + +/** + * _cogl_set_indirect_context: + * @indirect: TRUE if GL context is indirect + * + * Advises COGL that the GL context is indirect (commands are sent + * over a socket). COGL uses this information to try to avoid + * round-trips in its use of GL, for example. + * + * This function cannot be called "on the fly," only before COGL + * initializes. + */ +void +_cogl_set_indirect_context (gboolean indirect) +{ + /* we get called multiple times if someone creates + * more than the default stage + */ + if (_context != NULL) + { + if (indirect != _context->indirect) + g_warning ("Right now all stages will be treated as " + "either direct or indirect, ignoring attempt " + "to change to indirect=%d", indirect); + return; + } + + gl_is_indirect = indirect; +} diff --git a/clutter/cogl/gles/cogl-context.h b/clutter/cogl/gles/cogl-context.h index 041587c56..68c694549 100644 --- a/clutter/cogl/gles/cogl-context.h +++ b/clutter/cogl/gles/cogl-context.h @@ -28,6 +28,8 @@ #include "cogl-primitives.h" #include "cogl-clip-stack.h" +#include "cogl-matrix-stack.h" +#include "cogl-current-matrix.h" #include "cogl-gles2-wrapper.h" @@ -50,6 +52,12 @@ typedef struct gboolean enable_backface_culling; + gboolean indirect; + + /* Client-side matrix stack or NULL if none */ + CoglMatrixMode matrix_mode; + CoglMatrixStack *modelview_stack; + /* Cache of inverse projection matrix */ float inverse_projection[16]; diff --git a/clutter/cogl/gles/cogl-fbo.c b/clutter/cogl/gles/cogl-fbo.c index 3cf523a00..b52e1055a 100644 --- a/clutter/cogl/gles/cogl-fbo.c +++ b/clutter/cogl/gles/cogl-fbo.c @@ -206,33 +206,29 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen) from a non-screen buffer */ GE( glGetIntegerv (GL_VIEWPORT, ctx->viewport_store) ); - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); } else { /* Override viewport and matrix setup if redirecting from another offscreen buffer */ - GE( glMatrixMode (GL_PROJECTION) ); - GE( glLoadIdentity () ); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_identity (); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glLoadIdentity () ); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_identity (); } /* Setup new viewport and matrices */ GE( glViewport (0, 0, fbo->width, fbo->height) ); - GE( glTranslatef (-1.0, -1.0, 0) ); - GE( glScalef (((float)(2) / - (float)(fbo->width)), - ((float)(2) / - (float)(fbo->height)), - 1.0) ); + _cogl_current_matrix_translate (-1.0f, -1.0f, 0.0f); + _cogl_current_matrix_scale (2.0f / fbo->width, 2.0f / fbo->height, 1.0f); /* Bind offscreen framebuffer object */ GE( glBindFramebuffer (GL_FRAMEBUFFER, fbo->gl_handle) ); @@ -265,11 +261,11 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen) GE( glViewport (ctx->viewport_store[0], ctx->viewport_store[1], ctx->viewport_store[2], ctx->viewport_store[3]) ); - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPopMatrix () ); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_pop (); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPopMatrix () ); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_pop (); } /* Bind window framebuffer object */ diff --git a/clutter/cogl/gles/cogl-primitives.c b/clutter/cogl/gles/cogl-primitives.c index 0612d0216..d1ba14372 100644 --- a/clutter/cogl/gles/cogl-primitives.c +++ b/clutter/cogl/gles/cogl-primitives.c @@ -87,6 +87,7 @@ _cogl_path_stroke_nodes () COGL_MATERIAL_FLUSH_DISABLE_MASK, (guint32)~0, /* disable all texture layers */ NULL); + _cogl_current_matrix_state_flush (); while (path_start < ctx->path_nodes->len) { @@ -167,6 +168,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, GE( glColorMask (FALSE, FALSE, FALSE, FALSE) ); GE( glDepthMask (FALSE) ); + _cogl_current_matrix_state_flush (); while (path_start < path_size) { GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode), @@ -202,16 +204,18 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) ); /* Decrement all of the bits twice so that only pixels where the value is 3 will remain */ - GE( glPushMatrix () ); - GE( glLoadIdentity () ); - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); + + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); cogl_rectangle (-1.0, -1.0, 1.0, 1.0); cogl_rectangle (-1.0, -1.0, 1.0, 1.0); - GE( glPopMatrix () ); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPopMatrix () ); + _cogl_current_matrix_pop (); + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_pop (); } GE( glStencilMask (~(GLuint) 0) ); diff --git a/clutter/cogl/gles/cogl-texture.c b/clutter/cogl/gles/cogl-texture.c index dcf7dc6fa..945a101b8 100644 --- a/clutter/cogl/gles/cogl-texture.c +++ b/clutter/cogl/gles/cogl-texture.c @@ -504,18 +504,18 @@ _cogl_texture_download_from_gl (CoglTexture *tex, (0,0 in bottom-left corner to draw the texture upside-down so we match the way glReadPixels works) */ - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); - GE( glOrthof (0, (float)(viewport[2]), - 0, (float)(viewport[3]), - (float)(0), - (float)(100)) ); + _cogl_current_matrix_ortho (0, (float)(viewport[2]), + 0, (float)(viewport[3]), + (float)(0), + (float)(100)); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); /* Draw to all channels */ cogl_draw_buffer (COGL_WINDOW_BUFFER | COGL_MASK_BUFFER, 0); @@ -611,10 +611,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex, } /* Restore old state */ - glMatrixMode (GL_PROJECTION); - glPopMatrix (); - glMatrixMode (GL_MODELVIEW); - glPopMatrix (); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_pop (); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_pop (); cogl_draw_buffer (COGL_WINDOW_BUFFER, 0); @@ -2169,7 +2169,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, cogl_enable (enable_flags); GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer)); - + _cogl_current_matrix_state_flush (); GE (glDrawRangeElements (GL_TRIANGLES, 0, ctx->static_indices->len - 1, 6 * batch_len, @@ -2198,6 +2198,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, color == 2 ? 0xff : 0x00, 0xff); cogl_material_flush_gl_state (outline, NULL); + _cogl_current_matrix_state_flush (); GE( glDrawArrays (GL_LINE_LOOP, 4 * i, 4) ); } } @@ -2986,6 +2987,7 @@ _cogl_texture_sliced_polygon (CoglTextureVertex *vertices, COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, gl_handle, NULL); + _cogl_current_matrix_state_flush (); GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) ); } @@ -3069,6 +3071,7 @@ _cogl_multitexture_unsliced_polygon (CoglTextureVertex *vertices, COGL_MATERIAL_FLUSH_FALLBACK_MASK, fallback_mask, NULL); + _cogl_current_matrix_state_flush (); GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices)); } diff --git a/clutter/cogl/gles/cogl.c b/clutter/cogl/gles/cogl.c index 49f6335f5..ca669e46d 100644 --- a/clutter/cogl/gles/cogl.c +++ b/clutter/cogl/gles/cogl.c @@ -124,37 +124,6 @@ cogl_clear (const CoglColor *color) */ } -/* FIXME: inline most of these */ -void -cogl_push_matrix (void) -{ - GE( glPushMatrix() ); -} - -void -cogl_pop_matrix (void) -{ - GE( glPopMatrix() ); -} - -void -cogl_scale (float x, float y, float z) -{ - GE( glScalef (x, y, z) ); -} - -void -cogl_translate (float x, float y, float z) -{ - GE( glTranslatef (x, y, z) ); -} - -void -cogl_rotate (float angle, float x, float y, float z) -{ - GE( glRotatef (angle, x, y, z) ); -} - static inline gboolean cogl_toggle_flag (CoglContext *ctx, gulong new_flags, @@ -319,6 +288,7 @@ set_clip_plane (GLint plane_num, GLdouble plane[4]; #endif GLfloat angle; + CoglMatrix inverse_projection; _COGL_GET_CONTEXT (ctx, NO_RETVAL); /* Calculate the angle between the axes and the line crossing the @@ -326,18 +296,20 @@ set_clip_plane (GLint plane_num, angle = atan2f (vertex_b[1] - vertex_a[1], vertex_b[0] - vertex_a[0]) * (180.0/G_PI); - GE( glPushMatrix () ); + _cogl_current_matrix_push (); /* Load the identity matrix and multiply by the reverse of the projection matrix so we can specify the plane in screen coordinates */ - GE( glLoadIdentity () ); - GE( glMultMatrixf ((GLfloat *) ctx->inverse_projection) ); + _cogl_current_matrix_identity (); + cogl_matrix_init_from_array (&inverse_projection, + ctx->inverse_projection); + _cogl_current_matrix_multiply (&inverse_projection); /* Rotate about point a */ - GE( glTranslatef (vertex_a[0], vertex_a[1], vertex_a[2]) ); + _cogl_current_matrix_translate (vertex_a[0], vertex_a[1], vertex_a[2]); /* Rotate the plane by the calculated angle so that it will connect the two points */ - GE( glRotatef (angle, 0.0f, 0.0f, 1.0f) ); - GE( glTranslatef (-vertex_a[0], -vertex_a[1], -vertex_a[2]) ); + _cogl_current_matrix_rotate (angle, 0.0f, 0.0f, 1.0f); + _cogl_current_matrix_translate (-vertex_a[0], -vertex_a[1], -vertex_a[2]); plane[0] = 0; plane[1] = -1.0; @@ -349,7 +321,7 @@ set_clip_plane (GLint plane_num, GE( glClipPlane (plane_num, plane) ); #endif - GE( glPopMatrix () ); + _cogl_current_matrix_pop (); } void @@ -358,7 +330,10 @@ _cogl_set_clip_planes (float x_offset, float width, float height) { - GLfloat modelview[16], projection[16]; + CoglMatrix modelview_matrix; + CoglMatrix projection_matrix; + GLfloat *modelview; + GLfloat *projection; float vertex_tl[4] = { x_offset, y_offset, 0, 1.0 }; float vertex_tr[4] = { x_offset + width, y_offset, 0, 1.0 }; @@ -366,8 +341,18 @@ _cogl_set_clip_planes (float x_offset, float vertex_br[4] = { x_offset + width, y_offset + height, 0, 1.0 }; - GE( glGetFloatv (GL_MODELVIEW_MATRIX, modelview) ); - GE( glGetFloatv (GL_PROJECTION_MATRIX, projection) ); + /* hack alert: there's no way to get *and modify* + * CoglMatrix as a float array. So we just + * use a cast instead of cogl_matrix_get_array(), + * and know that we will not call any more CoglMatrix + * methods after we write to it directly. + */ + _cogl_get_matrix (COGL_MATRIX_PROJECTION, + &projection_matrix); + projection = (GLfloat*) &projection_matrix; + _cogl_get_matrix (COGL_MATRIX_MODELVIEW, + &modelview_matrix); + modelview = (GLfloat*) &modelview_matrix; project_vertex (modelview, projection, vertex_tl); project_vertex (modelview, projection, vertex_tr); @@ -436,15 +421,15 @@ _cogl_add_stencil_clip (float x_offset, only pixels where both the original stencil buffer and the rectangle are set will be valid */ GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); - GE( glMatrixMode (GL_PROJECTION) ); - GE( glPushMatrix () ); - GE( glLoadIdentity () ); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_push (); + _cogl_current_matrix_identity (); cogl_rectangle (-1.0, -1.0, 1.0, 1.0); - GE( glPopMatrix () ); - GE( glMatrixMode (GL_MODELVIEW) ); - GE( glPopMatrix () ); + _cogl_current_matrix_pop (); + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_pop (); } /* Restore the stencil mode */ @@ -452,14 +437,6 @@ _cogl_add_stencil_clip (float x_offset, GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) ); } -void -_cogl_set_matrix (const CoglMatrix *matrix) -{ - const GLfloat *gl_matrix = cogl_matrix_get_array (matrix); - - GE (glLoadMatrixf (gl_matrix)); -} - void _cogl_disable_stencil_buffer (void) { @@ -484,108 +461,6 @@ _cogl_disable_clip_planes (void) GE( glDisable (GL_CLIP_PLANE0) ); } -void -cogl_perspective (float fovy, - float aspect, - float zNear, - float zFar) -{ - float xmax, ymax; - float x, y, c, d; - float fovy_rad_half = (fovy * G_PI) / 360; - - GLfloat m[16]; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - memset (&m[0], 0, sizeof (m)); - - GE( glMatrixMode (GL_PROJECTION) ); - GE( glLoadIdentity () ); - - /* - * Based on the original algorithm in perspective(): - * - * 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax - * same true for y, hence: a == 0 && b == 0; - * - * 2) When working with small numbers, we are loosing significant - * precision - */ - ymax = (zNear * (sinf (fovy_rad_half) / cosf (fovy_rad_half))); - xmax = (ymax * aspect); - - x = (zNear / xmax); - y = (zNear / ymax); - c = (-(zFar + zNear) / ( zFar - zNear)); - d = (-(2 * zFar) * zNear) / (zFar - zNear); - -#define M(row,col) m[col*4+row] - M(0,0) = x; - M(1,1) = y; - M(2,2) = c; - M(2,3) = d; - M(3,2) = -1.0; - - GE( glMultMatrixf (m) ); - - GE( glMatrixMode (GL_MODELVIEW) ); - - /* Calculate and store the inverse of the matrix */ - memset (ctx->inverse_projection, 0, sizeof (float) * 16); - -#define m ctx->inverse_projection - M(0, 0) = (1.0 / x); - M(1, 1) = (1.0 / y); - M(2, 3) = -1.0; - M(3, 2) = (1.0 / d); - M(3, 3) = (c / d); -#undef m - -#undef M -} - -void -cogl_frustum (float left, - float right, - float bottom, - float top, - float z_near, - float z_far) -{ - float c, d; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - GE( glMatrixMode (GL_PROJECTION) ); - GE( glLoadIdentity () ); - - GE( glFrustumf (left, - right, - bottom, - top, - z_near, - z_far) ); - - GE( glMatrixMode (GL_MODELVIEW) ); - - /* Calculate and store the inverse of the matrix */ - memset (ctx->inverse_projection, 0, sizeof (float) * 16); - - c = - (z_far + z_near) / (z_far - z_near); - d = - (2 * (z_far * z_near)) / (z_far - z_near); - -#define M(row,col) ctx->inverse_projection[col*4+row] - M(0,0) = (right - left) / (2 * z_near); - M(0,3) = (right + left) / (2 * z_near); - M(1,1) = (top - bottom) / (2 * z_near); - M(1,3) = (top + bottom) / (2 * z_near); - M(2,3) = -1.0; - M(3,2) = 1.0 / d; - M(3,3) = c / d; -#undef M -} - void cogl_viewport (guint width, guint height) @@ -607,8 +482,8 @@ cogl_setup_viewport (guint width, GE( glViewport (0, 0, width, height) ); /* For Ortho projection. - * glOrthof (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); - */ + * _cogl_current_matrix_ortho (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); + */ cogl_perspective (fovy, aspect, z_near, z_far); @@ -621,13 +496,10 @@ cogl_setup_viewport (guint width, cogl_get_projection_matrix (&projection_matrix); z_camera = 0.5 * projection_matrix.xx; - GE( glLoadIdentity () ); - - GE( glTranslatef (-0.5f, -0.5f, -z_camera) ); - - GE( glScalef (1.0f / width, -1.0f / height, 1.0f / width) ); - - GE( glTranslatef (0.0f, -1.0 * height, 0.0f) ); + _cogl_current_matrix_identity (); + _cogl_current_matrix_translate (-0.5f, -0.5f, -z_camera); + _cogl_current_matrix_scale (1.0f / width, -1.0f / height, 1.0f / width); + _cogl_current_matrix_translate (0.0f, -1.0 * height, 0.0f); } static void @@ -679,28 +551,6 @@ cogl_features_available (CoglFeatureFlags features) return (ctx->feature_flags & features) == features; } -void -cogl_get_modelview_matrix (CoglMatrix *matrix) -{ - float m[16]; - glGetFloatv (GL_MODELVIEW_MATRIX, m); - /* Since it's internal to Cogl and CoglMatrix doesn't currently have - * any flag members, we could avoid this extra copy if it really - * bothers anyone */ - cogl_matrix_init_from_array (matrix, m); -} - -void -cogl_get_projection_matrix (CoglMatrix *matrix) -{ - float m[16]; - glGetFloatv (GL_PROJECTION_MATRIX, m); - /* Since it's internal to Cogl and CoglMatrix doesn't currently have - * any flag members, we could avoid this extra copy if it really - * bothers anyone */ - cogl_matrix_init_from_array (matrix, m); -} - void cogl_get_viewport (float v[4]) { @@ -796,3 +646,8 @@ cogl_disable_fog (void) glDisable (GL_FOG); } +void +cogl_flush_gl_state (int flags) +{ + _cogl_current_matrix_state_flush (); +} diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index f50225a00..12f54cb38 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -224,6 +224,9 @@ clutter_stage_glx_realize (ClutterActor *actor) g_critical ("Unable to create suitable GL context."); goto fail; } + + _cogl_set_indirect_context (!glXIsDirect (stage_x11->xdpy, + backend_glx->gl_context)); } CLUTTER_NOTE (BACKEND, "Marking stage as realized");