Merge branch 'cogl-client-matrix-stacks'
* cogl-client-matrix-stacks: Maintain the Cogl assumption that the modelview matrix is normally current Finish GLES{1,2} support for client side matrix stacks Explicitly make the modelview-matrix current in cogl_{rotate,transform,etc} Avoid casting CoglMatrix to a GLfloat * when calling glGetFloatv Removes need for casting const float * in _cogl_set_clip_planes Virtualize GL matrix operations and use a client-side matrix when GL is indirect
This commit is contained in:
commit
5af7c85fa2
@ -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
|
||||
|
18
cogl.h.in
18
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__
|
||||
|
@ -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
|
||||
|
476
common/cogl-current-matrix.c
Normal file
476
common/cogl-current-matrix.c
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Clutter COGL
|
||||
*
|
||||
* A basic GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Authored By Havoc Pennington <hp@pobox.com> 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"
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
#include "cogl-gles2-wrapper.h"
|
||||
|
||||
#define glFrustum(L,R,B,T,N,F) \
|
||||
cogl_wrap_glFrustumf((GLfloat)L, (GLfloat)R, (GLfloat)B, \
|
||||
(GLfloat)T, (GLfloat)N, (GLfloat)F)
|
||||
#elif defined (HAVE_COGL_GLES)
|
||||
|
||||
#define glFrustum(L,R,B,T,N,F) \
|
||||
glFrustumf((GLfloat)L, (GLfloat)R, (GLfloat)B, \
|
||||
(GLfloat)T, (GLfloat)N, (GLfloat)F)
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
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;
|
||||
GLfloat gl_matrix[16];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Note: we have a redundant copy happening here. If that turns out to be
|
||||
* a problem then, since this is internal to Cogl, we could pass the
|
||||
* CoglMatrix pointer directly to glGetFloatv; the only problem with that
|
||||
* is that if we later add internal flags to CoglMatrix they will need to
|
||||
* be initialized seperatly.
|
||||
*/
|
||||
GE (glGetFloatv (gl_mode, gl_matrix));
|
||||
cogl_matrix_init_from_array (matrix, gl_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_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_push ();
|
||||
}
|
||||
|
||||
void
|
||||
cogl_pop_matrix (void)
|
||||
{
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_pop ();
|
||||
}
|
||||
|
||||
void
|
||||
cogl_scale (float x, float y, float z)
|
||||
{
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_scale (x, y, z);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_translate (float x, float y, float z)
|
||||
{
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_translate (x, y, z);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_rotate (float angle, float x, float y, float z)
|
||||
{
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_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
|
||||
}
|
91
common/cogl-current-matrix.h
Normal file
91
common/cogl-current-matrix.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Clutter COGL
|
||||
*
|
||||
* A basic GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Authored By Havoc Pennington <hp@pobox.com> 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 <cogl/cogl-matrix.h>
|
||||
|
||||
/**
|
||||
* 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 */
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
327
common/cogl-matrix-stack.c
Normal file
327
common/cogl-matrix-stack.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Clutter COGL
|
||||
*
|
||||
* A basic GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Authored By Havoc Pennington <hp@pobox.com> 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));
|
||||
}
|
67
common/cogl-matrix-stack.h
Normal file
67
common/cogl-matrix-stack.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Clutter COGL
|
||||
*
|
||||
* A basic GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Authored By Havoc Pennington <hp@pobox.com> 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 <cogl/cogl-matrix.h>
|
||||
|
||||
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 */
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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));
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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,28 @@ _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_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_push ();
|
||||
_cogl_current_matrix_identity ();
|
||||
|
||||
/* Cogl generally assumes the modelview matrix is current, so since
|
||||
* cogl_rectangle will be flushing GL state and emitting geometry
|
||||
* to OpenGL it will be confused if we leave the projection matrix
|
||||
* active... */
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_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_PROJECTION);
|
||||
_cogl_current_matrix_pop ();
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
}
|
||||
|
||||
GE( glStencilMask (~(GLuint) 0) );
|
||||
|
@ -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));
|
||||
}
|
||||
|
268
gl/cogl.c
268
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,
|
||||
@ -357,29 +326,20 @@ cogl_set_source_color (const CoglColor *color)
|
||||
}
|
||||
|
||||
static void
|
||||
apply_matrix (const float *matrix, float *vertex)
|
||||
{
|
||||
int x, y;
|
||||
float vertex_out[4] = { 0 };
|
||||
|
||||
for (y = 0; y < 4; y++)
|
||||
for (x = 0; x < 4; x++)
|
||||
vertex_out[y] += vertex[x] * matrix[y + x * 4];
|
||||
|
||||
memcpy (vertex, vertex_out, sizeof (vertex_out));
|
||||
}
|
||||
|
||||
static void
|
||||
project_vertex (float *modelview,
|
||||
float *project,
|
||||
project_vertex (const CoglMatrix *modelview_matrix,
|
||||
const CoglMatrix *projection_matrix,
|
||||
float *vertex)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Apply the modelview matrix */
|
||||
apply_matrix (modelview, vertex);
|
||||
cogl_matrix_transform_point (modelview_matrix,
|
||||
&vertex[0], &vertex[1],
|
||||
&vertex[2], &vertex[3]);
|
||||
/* Apply the projection matrix */
|
||||
apply_matrix (project, vertex);
|
||||
cogl_matrix_transform_point (projection_matrix,
|
||||
&vertex[0], &vertex[1],
|
||||
&vertex[2], &vertex[3]);
|
||||
/* Convert from homogenized coordinates */
|
||||
for (i = 0; i < 4; i++)
|
||||
vertex[i] /= vertex[3];
|
||||
@ -396,6 +356,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 +364,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 +389,7 @@ set_clip_plane (GLint plane_num,
|
||||
GE( glClipPlane (plane_num, plane) );
|
||||
#endif
|
||||
|
||||
GE( glPopMatrix () );
|
||||
_cogl_current_matrix_pop ();
|
||||
}
|
||||
|
||||
void
|
||||
@ -435,7 +398,8 @@ _cogl_set_clip_planes (float x_offset,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
GLfloat modelview[16], projection[16];
|
||||
CoglMatrix modelview_matrix;
|
||||
CoglMatrix projection_matrix;
|
||||
|
||||
float vertex_tl[4] = { x_offset, y_offset, 0, 1.0 };
|
||||
float vertex_tr[4] = { x_offset + width, y_offset, 0, 1.0 };
|
||||
@ -443,13 +407,15 @@ _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) );
|
||||
_cogl_get_matrix (COGL_MATRIX_PROJECTION,
|
||||
&projection_matrix);
|
||||
_cogl_get_matrix (COGL_MATRIX_MODELVIEW,
|
||||
&modelview_matrix);
|
||||
|
||||
project_vertex (modelview, projection, vertex_tl);
|
||||
project_vertex (modelview, projection, vertex_tr);
|
||||
project_vertex (modelview, projection, vertex_bl);
|
||||
project_vertex (modelview, projection, vertex_br);
|
||||
project_vertex (&modelview_matrix, &projection_matrix, vertex_tl);
|
||||
project_vertex (&modelview_matrix, &projection_matrix, vertex_tr);
|
||||
project_vertex (&modelview_matrix, &projection_matrix, vertex_bl);
|
||||
project_vertex (&modelview_matrix, &projection_matrix, vertex_br);
|
||||
|
||||
/* If the order of the top and bottom lines is different from the
|
||||
order of the left and right lines then the clip rect must have
|
||||
@ -513,15 +479,27 @@ _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_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_push ();
|
||||
_cogl_current_matrix_identity ();
|
||||
|
||||
/* Cogl generally assumes the modelview matrix is current, so since
|
||||
* cogl_rectangle will be flushing GL state and emitting geometry
|
||||
* to OpenGL it will be confused if we leave the projection matrix
|
||||
* active... */
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_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_PROJECTION);
|
||||
_cogl_current_matrix_pop ();
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
}
|
||||
|
||||
/* Restore the stencil mode */
|
||||
@ -529,14 +507,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 +531,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 +552,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 +599,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 +989,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 +1079,8 @@ cogl_disable_fog (void)
|
||||
glDisable (GL_FOG);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_flush_gl_state (int flags)
|
||||
{
|
||||
_cogl_current_matrix_state_flush ();
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -1505,6 +1505,8 @@ cogl_wrap_glGetIntegerv (GLenum pname, GLint *params)
|
||||
void
|
||||
cogl_wrap_glGetFloatv (GLenum pname, GLfloat *params)
|
||||
{
|
||||
CoglGles2WrapperTextureUnit *texture_unit;
|
||||
|
||||
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
|
||||
|
||||
switch (pname)
|
||||
@ -1519,6 +1521,14 @@ cogl_wrap_glGetFloatv (GLenum pname, GLfloat *params)
|
||||
sizeof (GLfloat) * 16);
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_MATRIX:
|
||||
texture_unit = w->texture_units + w->active_texture_unit;
|
||||
memcpy (params,
|
||||
texture_unit->texture_stack
|
||||
+ texture_unit->texture_stack_pos * 16,
|
||||
sizeof (GLfloat) * 16);
|
||||
break;
|
||||
|
||||
case GL_VIEWPORT:
|
||||
glGetFloatv (GL_VIEWPORT, params);
|
||||
break;
|
||||
|
@ -255,6 +255,7 @@ struct _CoglGles2WrapperShader
|
||||
|
||||
#define GL_MODELVIEW_MATRIX 0x0BA6
|
||||
#define GL_PROJECTION_MATRIX 0x0BA7
|
||||
#define GL_TEXTURE_MATRIX 0x0BA8
|
||||
|
||||
#define GL_GENERATE_MIPMAP 0x8191
|
||||
|
||||
|
@ -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,28 @@ _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_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_push ();
|
||||
_cogl_current_matrix_identity ();
|
||||
|
||||
/* Cogl generally assumes the modelview matrix is current, so since
|
||||
* cogl_rectangle will be flushing GL state and emitting geometry
|
||||
* to OpenGL it will be confused if we leave the projection matrix
|
||||
* active... */
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_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_PROJECTION);
|
||||
_cogl_current_matrix_pop ();
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
}
|
||||
|
||||
GE( glStencilMask (~(GLuint) 0) );
|
||||
|
@ -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));
|
||||
}
|
||||
|
247
gles/cogl.c
247
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,27 @@ _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_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_push ();
|
||||
_cogl_current_matrix_identity ();
|
||||
|
||||
/* Cogl generally assumes the modelview matrix is current, so since
|
||||
* cogl_rectangle will be flushing GL state and emitting geometry
|
||||
* to OpenGL it will be confused if we leave the projection matrix
|
||||
* active... */
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_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_PROJECTION);
|
||||
_cogl_current_matrix_pop ();
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
}
|
||||
|
||||
/* Restore the stencil mode */
|
||||
@ -452,14 +449,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 +473,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 +494,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 +508,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 +563,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 +658,8 @@ cogl_disable_fog (void)
|
||||
glDisable (GL_FOG);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_flush_gl_state (int flags)
|
||||
{
|
||||
_cogl_current_matrix_state_flush ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user