Bug 945 - Clipping+fbo cloning bugs

* clutter/cogl/gl/cogl.c: 
	* clutter/cogl/gles/cogl.c: 
	* clutter/cogl/cogl.h.in: Add cogl_clip_stack_save,
	cogl_clip_stack_restore, cogl_viewport and cogl_frustum.

	* clutter/cogl/gl/cogl-fbo.h: 
	* clutter/cogl/gl/cogl-fbo.c: Try to attach a stencil buffer when
	creating an FBO.

	* clutter/cogl/common/cogl-clip-stack.c: Add functions to save and
	restore the whole state of the stack.

	* clutter/clutter-texture.c (clutter_texture_paint): When
	rendering the FBO source, setup a temporary asymmetric perspective
	projection matrix to render it as it would appear on screen.

	* clutter/clutter-private.h: 
	* clutter/clutter-actor.c
	(_clutter_actor_apply_modelview_transform_recursive): No longer
	static and exported in clutter-private.h
This commit is contained in:
Neil Roberts 2008-08-01 12:23:57 +00:00
parent 88a561fa01
commit ef76d8e5e2
11 changed files with 307 additions and 33 deletions

View File

@ -338,14 +338,35 @@ void cogl_get_bitmasks (gint *red,
* @z_near: Nearest visible point * @z_near: Nearest visible point
* @z_far: Furthest visible point along the z-axis * @z_far: Furthest visible point along the z-axis
* *
* Multiplies the current set matrix with a projection matrix based * Replaces the current projection matrix with a perspective matrix
* on the provided values. * based on the provided values.
*/ */
void cogl_perspective (ClutterFixed fovy, void cogl_perspective (ClutterFixed fovy,
ClutterFixed aspect, ClutterFixed aspect,
ClutterFixed z_near, ClutterFixed z_near,
ClutterFixed z_far); ClutterFixed z_far);
/**
* cogl_frustum:
* @left: Left clipping plane
* @right: Right clipping plane
* @bottom: Bottom clipping plane
* @top: Top clipping plane
* @z_near: Nearest visible point
* @z_far: Furthest visible point along the z-axis
*
* Replaces the current projection matrix with a perspective matrix
* for the given viewing frustum.
*
* Since: 0.8.2
*/
void cogl_frustum (ClutterFixed left,
ClutterFixed right,
ClutterFixed bottom,
ClutterFixed top,
ClutterFixed z_near,
ClutterFixed z_far);
/** /**
* cogl_setup_viewport: * cogl_setup_viewport:
* @width: Width of the viewport * @width: Width of the viewport
@ -369,6 +390,18 @@ void cogl_setup_viewport (guint width,
ClutterFixed z_near, ClutterFixed z_near,
ClutterFixed z_far); ClutterFixed z_far);
/**
* cogl_viewport:
* @width: Width of the viewport
* @height: Height of the viewport
*
* Replace the current viewport with the given values.
*
* Since: 0.8.2
*/
void cogl_viewport (guint width,
guint height);
/** /**
* cogl_push_matrix: * cogl_push_matrix:
* *
@ -511,6 +544,29 @@ void cogl_clip_set (ClutterFixed x_offset,
*/ */
void cogl_clip_unset (void); void cogl_clip_unset (void);
/**
* cogl_clip_stack_save:
*
* Save the entire state of the clipping stack and then clear all
* clipping. The previous state can be returned to with
* cogl_clip_stack_restore(). Each call to cogl_clip_set() after this
* must be matched by a call to cogl_clip_unset() before calling
* cogl_clip_stack_restore().
*
* Since: 0.8.2
*/
void cogl_clip_stack_save (void);
/**
* cogl_clip_stack_restore:
*
* Restore the state of the clipping stack that was previously saved
* by cogl_clip_stack_save().
*
* Since: 0.8.2
*/
void cogl_clip_stack_restore (void);
/** /**
* cogl_enable_depth_test: * cogl_enable_depth_test:
* @setting: %TRUE to enable depth testing or %FALSE to disable. * @setting: %TRUE to enable depth testing or %FALSE to disable.

View File

@ -50,6 +50,12 @@ typedef struct _CoglClipStackEntry CoglClipStackEntry;
struct _CoglClipStackEntry struct _CoglClipStackEntry
{ {
/* If this is set then this entry clears the clip stack. This is
used to clear the stack when drawing an FBO put to keep the
entries so they can be restored when the FBO drawing is
completed */
gboolean clear;
/* The rectangle for this clip */ /* The rectangle for this clip */
ClutterFixed x_offset; ClutterFixed x_offset;
ClutterFixed y_offset; ClutterFixed y_offset;
@ -61,7 +67,6 @@ struct _CoglClipStackEntry
}; };
static GList *cogl_clip_stack_top = NULL; static GList *cogl_clip_stack_top = NULL;
static GList *cogl_clip_stack_bottom = NULL;
static int cogl_clip_stack_depth = 0; static int cogl_clip_stack_depth = 0;
static void static void
@ -93,6 +98,7 @@ cogl_clip_set (ClutterFixed x_offset,
CoglClipStackEntry *entry = g_slice_new (CoglClipStackEntry); CoglClipStackEntry *entry = g_slice_new (CoglClipStackEntry);
/* Make a new entry */ /* Make a new entry */
entry->clear = FALSE;
entry->x_offset = x_offset; entry->x_offset = x_offset;
entry->y_offset = y_offset; entry->y_offset = y_offset;
entry->width = width; entry->width = width;
@ -105,8 +111,6 @@ cogl_clip_set (ClutterFixed x_offset,
/* Store it in the stack */ /* Store it in the stack */
cogl_clip_stack_top = g_list_prepend (cogl_clip_stack_top, entry); cogl_clip_stack_top = g_list_prepend (cogl_clip_stack_top, entry);
if (cogl_clip_stack_bottom == NULL)
cogl_clip_stack_bottom = cogl_clip_stack_top;
} }
void void
@ -118,8 +122,6 @@ cogl_clip_unset (void)
g_slice_free (CoglClipStackEntry, cogl_clip_stack_top->data); g_slice_free (CoglClipStackEntry, cogl_clip_stack_top->data);
cogl_clip_stack_top = g_list_delete_link (cogl_clip_stack_top, cogl_clip_stack_top = g_list_delete_link (cogl_clip_stack_top,
cogl_clip_stack_top); cogl_clip_stack_top);
if (cogl_clip_stack_top == NULL)
cogl_clip_stack_bottom = NULL;
cogl_clip_stack_depth--; cogl_clip_stack_depth--;
/* Rebuild the clip */ /* Rebuild the clip */
@ -131,7 +133,7 @@ _cogl_clip_stack_rebuild (gboolean just_stencil)
{ {
int has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES); int has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
GList *node; GList *node;
int depth = 1; int depth = 0;
/* Disable clip planes if the stack is empty */ /* Disable clip planes if the stack is empty */
if (has_clip_planes && cogl_clip_stack_depth < 1) if (has_clip_planes && cogl_clip_stack_depth < 1)
@ -141,8 +143,14 @@ _cogl_clip_stack_rebuild (gboolean just_stencil)
if (cogl_clip_stack_depth < (has_clip_planes ? 2 : 1)) if (cogl_clip_stack_depth < (has_clip_planes ? 2 : 1))
_cogl_disable_stencil_buffer (); _cogl_disable_stencil_buffer ();
/* Find the bottom of the stack */
for (node = cogl_clip_stack_top; depth < cogl_clip_stack_depth - 1;
node = node->next)
depth++;
/* Re-add every entry from the bottom of the stack up */ /* Re-add every entry from the bottom of the stack up */
for (node = cogl_clip_stack_bottom; node; node = node->prev, depth++) depth = 1;
for (; depth <= cogl_clip_stack_depth; node = node->prev, depth++)
if (!just_stencil || !has_clip_planes || depth > 1) if (!just_stencil || !has_clip_planes || depth > 1)
{ {
const CoglClipStackEntry *entry = (CoglClipStackEntry *) node->data; const CoglClipStackEntry *entry = (CoglClipStackEntry *) node->data;
@ -156,12 +164,16 @@ _cogl_clip_stack_rebuild (gboolean just_stencil)
void void
_cogl_clip_stack_merge (void) _cogl_clip_stack_merge (void)
{ {
GList *node = cogl_clip_stack_bottom; GList *node = cogl_clip_stack_top;
int i;
/* Merge the current clip stack on top of whatever is in the stencil /* Merge the current clip stack on top of whatever is in the stencil
buffer */ buffer */
if (node) if (cogl_clip_stack_depth)
{ {
for (i = 0; i < cogl_clip_stack_depth - 1; i++)
node = node->next;
/* Skip the first entry if we have clipping planes */ /* Skip the first entry if we have clipping planes */
if (cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES)) if (cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES))
node = node->prev; node = node->prev;
@ -178,3 +190,43 @@ _cogl_clip_stack_merge (void)
} }
} }
} }
void
cogl_clip_stack_save (void)
{
CoglClipStackEntry *entry = g_slice_new (CoglClipStackEntry);
/* Push an entry into the stack to mark that it should be cleared */
entry->clear = TRUE;
cogl_clip_stack_top = g_list_prepend (cogl_clip_stack_top, entry);
/* Reset the depth to zero */
cogl_clip_stack_depth = 0;
/* Rebuilding the stack will now disabling all clipping */
_cogl_clip_stack_rebuild (FALSE);
}
void
cogl_clip_stack_restore (void)
{
GList *node;
/* The top of the stack should be a clear marker */
g_assert (cogl_clip_stack_top);
g_assert (((CoglClipStackEntry *) cogl_clip_stack_top->data)->clear);
/* Remove the top entry */
g_slice_free (CoglClipStackEntry, cogl_clip_stack_top->data);
cogl_clip_stack_top = g_list_delete_link (cogl_clip_stack_top,
cogl_clip_stack_top);
/* Recalculate the depth of the stack */
cogl_clip_stack_depth = 0;
for (node = cogl_clip_stack_top;
node && !((CoglClipStackEntry *) node->data)->clear;
node = node->next)
cogl_clip_stack_depth++;
_cogl_clip_stack_rebuild (FALSE);
}

View File

@ -26,11 +26,6 @@
#ifndef __COGL_CLIP_STACK_H #ifndef __COGL_CLIP_STACK_H
#define __COGL_CLIP_STACK_H #define __COGL_CLIP_STACK_H
void cogl_clip_set (ClutterFixed x_offset,
ClutterFixed y_offset,
ClutterFixed width,
ClutterFixed height);
void cogl_clip_unset (void);
void _cogl_clip_stack_rebuild (gboolean just_stencil); void _cogl_clip_stack_rebuild (gboolean just_stencil);
void _cogl_clip_stack_merge (void); void _cogl_clip_stack_merge (void);

View File

@ -13,7 +13,9 @@ CoglPixelFormat
CoglBufferTarget CoglBufferTarget
<SUBSECTION> <SUBSECTION>
cogl_perspective cogl_perspective
cogl_frustum
cogl_setup_viewport cogl_setup_viewport
cogl_viewport
cogl_get_modelview_matrix cogl_get_modelview_matrix
cogl_get_projection_matrix cogl_get_projection_matrix
cogl_get_viewport cogl_get_viewport
@ -28,6 +30,8 @@ cogl_rotate
<SUBSECTION> <SUBSECTION>
cogl_clip_set cogl_clip_set
cogl_clip_unset cogl_clip_unset
cogl_clip_stack_save
cogl_clip_stack_restore
<SUBSECTION> <SUBSECTION>
cogl_enable_depth_test cogl_enable_depth_test
cogl_alpha_func cogl_alpha_func

View File

@ -68,6 +68,7 @@ typedef struct
/* Relying on glext.h to define these */ /* Relying on glext.h to define these */
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT; COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
COGL_PFNGLBINDRENDERBUFFEREXTPROC pf_glBindRenderbufferEXT; COGL_PFNGLBINDRENDERBUFFEREXTPROC pf_glBindRenderbufferEXT;
COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC pf_glRenderbufferStorageEXT; COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC pf_glRenderbufferStorageEXT;
COGL_PFNGLGENFRAMEBUFFERSEXTPROC pf_glGenFramebuffersEXT; COGL_PFNGLGENFRAMEBUFFERSEXTPROC pf_glGenFramebuffersEXT;

View File

@ -37,6 +37,7 @@
/* Expecting EXT functions not to be defined - redirect to pointers in context */ /* Expecting EXT functions not to be defined - redirect to pointers in context */
#define glGenRenderbuffersEXT ctx->pf_glGenRenderbuffersEXT #define glGenRenderbuffersEXT ctx->pf_glGenRenderbuffersEXT
#define glDeleteRenderbuffersEXT ctx->pf_glDeleteRenderbuffersEXT
#define glBindRenderbufferEXT ctx->pf_glBindRenderbufferEXT #define glBindRenderbufferEXT ctx->pf_glBindRenderbufferEXT
#define glRenderbufferStorageEXT ctx->pf_glRenderbufferStorageEXT #define glRenderbufferStorageEXT ctx->pf_glRenderbufferStorageEXT
#define glGenFramebuffersEXT ctx->pf_glGenFramebuffersEXT #define glGenFramebuffersEXT ctx->pf_glGenFramebuffersEXT
@ -68,6 +69,7 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
CoglTexSliceSpan *y_span; CoglTexSliceSpan *y_span;
GLuint tex_gl_handle; GLuint tex_gl_handle;
GLuint fbo_gl_handle; GLuint fbo_gl_handle;
GLuint gl_stencil_handle;
GLenum status; GLenum status;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
@ -92,21 +94,47 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0); y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0);
tex_gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); tex_gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0);
/* Create a renderbuffer for stenciling */
GE( glGenRenderbuffersEXT (1, &gl_stencil_handle) );
GE( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, gl_stencil_handle) );
GE( glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT,
cogl_texture_get_width (texhandle),
cogl_texture_get_height (texhandle)) );
GE( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, 0) );
/* Generate framebuffer */ /* Generate framebuffer */
glGenFramebuffersEXT (1, &fbo_gl_handle); glGenFramebuffersEXT (1, &fbo_gl_handle);
GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo_gl_handle) ); GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo_gl_handle) );
GE( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GE( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
tex->gl_target, tex_gl_handle, 0) ); tex->gl_target, tex_gl_handle, 0) );
GE( glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, gl_stencil_handle) );
/* Make sure it's complete */ /* Make sure it's complete */
status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT); status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{ {
GE( glDeleteFramebuffersEXT (1, &fbo_gl_handle) ); /* Stencil renderbuffers aren't always supported. Try again
GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) ); without the stencil buffer */
return COGL_INVALID_HANDLE; GE( glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT,
0) );
GE( glDeleteRenderbuffersEXT (1, &gl_stencil_handle) );
gl_stencil_handle = 0;
status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
/* Still failing, so give up */
GE( glDeleteFramebuffersEXT (1, &fbo_gl_handle) );
GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
return COGL_INVALID_HANDLE;
}
} }
GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) ); GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
@ -114,10 +142,11 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
/* Allocate and init a CoglFbo object (store non-wasted size /* Allocate and init a CoglFbo object (store non-wasted size
for subsequent blits and viewport setup) */ for subsequent blits and viewport setup) */
fbo = (CoglFbo*) g_malloc (sizeof (CoglFbo)); fbo = (CoglFbo*) g_malloc (sizeof (CoglFbo));
fbo->ref_count = 1; fbo->ref_count = 1;
fbo->width = x_span->size - x_span->waste; fbo->width = x_span->size - x_span->waste;
fbo->height = y_span->size - y_span->waste; fbo->height = y_span->size - y_span->waste;
fbo->gl_handle = fbo_gl_handle; fbo->gl_handle = fbo_gl_handle;
fbo->gl_stencil_handle = gl_stencil_handle;
COGL_HANDLE_DEBUG_NEW (offscreen, fbo); COGL_HANDLE_DEBUG_NEW (offscreen, fbo);
@ -140,7 +169,8 @@ _cogl_offscreen_free (CoglFbo *fbo)
/* Frees FBO resources but its handle is not /* Frees FBO resources but its handle is not
released! Do that separately before this! */ released! Do that separately before this! */
if (fbo->gl_stencil_handle)
GE( glDeleteRenderbuffersEXT (1, &fbo->gl_stencil_handle) );
GE( glDeleteFramebuffersEXT (1, &fbo->gl_handle) ); GE( glDeleteFramebuffersEXT (1, &fbo->gl_handle) );
g_free (fbo); g_free (fbo);
} }

View File

@ -32,6 +32,7 @@ typedef struct
int width; int width;
int height; int height;
GLuint gl_handle; GLuint gl_handle;
GLuint gl_stencil_handle;
} CoglFbo; } CoglFbo;

View File

@ -746,6 +746,9 @@ cogl_perspective (ClutterFixed fovy,
memset (&m[0], 0, sizeof (m)); memset (&m[0], 0, sizeof (m));
GE( glMatrixMode (GL_PROJECTION) );
GE( glLoadIdentity () );
/* /*
* Based on the original algorithm in perspective(): * Based on the original algorithm in perspective():
* *
@ -773,6 +776,8 @@ cogl_perspective (ClutterFixed fovy,
GE( glMultMatrixf (m) ); GE( glMultMatrixf (m) );
GE( glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */ /* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (GLfloat) * 16); memset (ctx->inverse_projection, 0, sizeof (GLfloat) * 16);
@ -786,6 +791,60 @@ cogl_perspective (ClutterFixed fovy,
#undef M #undef M
} }
void
cogl_frustum (ClutterFixed left,
ClutterFixed right,
ClutterFixed bottom,
ClutterFixed top,
ClutterFixed z_near,
ClutterFixed z_far)
{
GLfloat c, d;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE( glMatrixMode (GL_PROJECTION) );
GE( glLoadIdentity () );
GE( glFrustum (CLUTTER_FIXED_TO_DOUBLE (left),
CLUTTER_FIXED_TO_DOUBLE (right),
CLUTTER_FIXED_TO_DOUBLE (bottom),
CLUTTER_FIXED_TO_DOUBLE (top),
CLUTTER_FIXED_TO_DOUBLE (z_near),
CLUTTER_FIXED_TO_DOUBLE (z_far)) );
GE( glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (GLfloat) * 16);
c = -CLUTTER_FIXED_TO_FLOAT (z_far + z_near)
/ CLUTTER_FIXED_TO_FLOAT (z_far - z_near);
d = -CLUTTER_FIXED_TO_FLOAT (2 * CFX_QMUL (z_far, z_near))
/ CLUTTER_FIXED_TO_FLOAT (z_far - z_near);
#define M(row,col) ctx->inverse_projection[col*4+row]
M(0,0) = CLUTTER_FIXED_TO_FLOAT (right - left)
/ CLUTTER_FIXED_TO_FLOAT (2 * z_near);
M(0,3) = CLUTTER_FIXED_TO_FLOAT (right + left)
/ CLUTTER_FIXED_TO_FLOAT (2 * z_near);
M(1,1) = CLUTTER_FIXED_TO_FLOAT (top - bottom)
/ CLUTTER_FIXED_TO_FLOAT (2 * z_near);
M(1,3) = CLUTTER_FIXED_TO_FLOAT (top + bottom)
/ CLUTTER_FIXED_TO_FLOAT (2 * z_near);
M(2,3) = -1.0f;
M(3,2) = 1.0f / d;
M(3,3) = c / d;
#undef M
}
void
cogl_viewport (guint width,
guint height)
{
GE( glViewport (0, 0, width, height) );
}
void void
cogl_setup_viewport (guint width, cogl_setup_viewport (guint width,
guint height, guint height,
@ -798,12 +857,8 @@ cogl_setup_viewport (guint width,
GE( glViewport (0, 0, width, height) ); GE( glViewport (0, 0, width, height) );
GE( glMatrixMode (GL_PROJECTION) );
GE( glLoadIdentity () );
cogl_perspective (fovy, aspect, z_near, z_far); cogl_perspective (fovy, aspect, z_near, z_far);
GE( glMatrixMode (GL_MODELVIEW) );
GE( glLoadIdentity () ); GE( glLoadIdentity () );
/* /*
@ -969,6 +1024,10 @@ _cogl_features_init ()
(COGL_PFNGLGENRENDERBUFFERSEXTPROC) (COGL_PFNGLGENRENDERBUFFERSEXTPROC)
cogl_get_proc_address ("glGenRenderbuffersEXT"); cogl_get_proc_address ("glGenRenderbuffersEXT");
ctx->pf_glDeleteRenderbuffersEXT =
(COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
cogl_get_proc_address ("glDeleteRenderbuffersEXT");
ctx->pf_glBindRenderbufferEXT = ctx->pf_glBindRenderbufferEXT =
(COGL_PFNGLBINDRENDERBUFFEREXTPROC) (COGL_PFNGLBINDRENDERBUFFEREXTPROC)
cogl_get_proc_address ("glBindRenderbufferEXT"); cogl_get_proc_address ("glBindRenderbufferEXT");

View File

@ -666,6 +666,31 @@ cogl_wrap_glMultMatrixx (const GLfixed *m)
cogl_wrap_glMultMatrix (new_matrix); cogl_wrap_glMultMatrix (new_matrix);
} }
void
cogl_wrap_glFrustumx (GLfixed left, GLfixed right,
GLfixed bottom, GLfixed top,
GLfixed z_near, GLfixed z_far)
{
float matrix[16];
float two_near = CLUTTER_FIXED_TO_FLOAT (2 * z_near);
memset (matrix, 0, sizeof (matrix));
matrix[0] = two_near / CLUTTER_FIXED_TO_FLOAT (right - left);
matrix[5] = two_near / CLUTTER_FIXED_TO_FLOAT (top - bottom);
matrix[8] = CLUTTER_FIXED_TO_FLOAT (right + left)
/ CLUTTER_FIXED_TO_FLOAT (right - left);
matrix[9] = CLUTTER_FIXED_TO_FLOAT (top + bottom)
/ CLUTTER_FIXED_TO_FLOAT (top - bottom);
matrix[10] = -CLUTTER_FIXED_TO_FLOAT (z_far + z_near)
/ CLUTTER_FIXED_TO_FLOAT (z_far - z_near);
matrix[11] = -1.0f;
matrix[14] = -two_near * CLUTTER_FIXED_TO_FLOAT (z_far)
/ CLUTTER_FIXED_TO_FLOAT (z_far - z_near);
cogl_wrap_glMultMatrix (matrix);
}
void void
cogl_wrap_glScalex (GLfixed x, GLfixed y, GLfixed z) cogl_wrap_glScalex (GLfixed x, GLfixed y, GLfixed z)
{ {

View File

@ -204,6 +204,9 @@ void cogl_wrap_glPopMatrix ();
void cogl_wrap_glMatrixMode (GLenum mode); void cogl_wrap_glMatrixMode (GLenum mode);
void cogl_wrap_glLoadIdentity (); void cogl_wrap_glLoadIdentity ();
void cogl_wrap_glMultMatrixx (const GLfixed *m); void cogl_wrap_glMultMatrixx (const GLfixed *m);
void cogl_wrap_glFrustumx (GLfixed left, GLfixed right,
GLfixed bottom, GLfixed top,
GLfixed z_near, GLfixed z_far);
void cogl_wrap_glScalex (GLfixed x, GLfixed y, GLfixed z); void cogl_wrap_glScalex (GLfixed x, GLfixed y, GLfixed z);
void cogl_wrap_glTranslatex (GLfixed x, GLfixed y, GLfixed z); void cogl_wrap_glTranslatex (GLfixed x, GLfixed y, GLfixed z);
void cogl_wrap_glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); void cogl_wrap_glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
@ -268,6 +271,7 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program);
#define cogl_wrap_glMatrixMode glMatrixMode #define cogl_wrap_glMatrixMode glMatrixMode
#define cogl_wrap_glLoadIdentity glLoadIdentity #define cogl_wrap_glLoadIdentity glLoadIdentity
#define cogl_wrap_glMultMatrixx glMultMatrixx #define cogl_wrap_glMultMatrixx glMultMatrixx
#define cogl_wrap_glFrustumx glFrustumx
#define cogl_wrap_glScalex glScalex #define cogl_wrap_glScalex glScalex
#define cogl_wrap_glTranslatex glTranslatex #define cogl_wrap_glTranslatex glTranslatex
#define cogl_wrap_glRotatex glRotatex #define cogl_wrap_glRotatex glRotatex

View File

@ -661,7 +661,10 @@ cogl_perspective (ClutterFixed fovy,
memset (&m[0], 0, sizeof (m)); memset (&m[0], 0, sizeof (m));
/* GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glLoadIdentity () );
/*
* Based on the original algorithm in perspective(): * Based on the original algorithm in perspective():
* *
* 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax * 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax
@ -688,6 +691,8 @@ cogl_perspective (ClutterFixed fovy,
GE( cogl_wrap_glMultMatrixx (m) ); GE( cogl_wrap_glMultMatrixx (m) );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */ /* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (ClutterFixed) * 16); memset (ctx->inverse_projection, 0, sizeof (ClutterFixed) * 16);
@ -702,6 +707,51 @@ cogl_perspective (ClutterFixed fovy,
#undef M #undef M
} }
void
cogl_frustum (ClutterFixed left,
ClutterFixed right,
ClutterFixed bottom,
ClutterFixed top,
ClutterFixed z_near,
ClutterFixed z_far)
{
ClutterFixed c, d;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glLoadIdentity () );
GE( cogl_wrap_glFrustumx (left, right,
bottom, top,
z_near, z_far) );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (ClutterFixed) * 16);
c = -CFX_QDIV (z_far + z_near, z_far - z_near);
d = -CFX_QDIV (2 * CFX_QMUL (z_far, z_near), z_far - z_near);
#define M(row,col) ctx->inverse_projection[col*4+row]
M(0,0) = CFX_QDIV (right - left, 2 * z_near);
M(0,3) = CFX_QDIV (right + left, 2 * z_near);
M(1,1) = CFX_QDIV (top - bottom, 2 * z_near);
M(1,3) = CFX_QDIV (top + bottom, 2 * z_near);
M(2,3) = -CFX_ONE;
M(3,2) = CFX_QDIV (CFX_ONE, d);
M(3,3) = CFX_QDIV (c, d);
#undef M
}
void
cogl_viewport (guint width,
guint height)
{
GE( glViewport (0, 0, width, height) );
}
void void
cogl_setup_viewport (guint w, cogl_setup_viewport (guint w,
guint h, guint h,
@ -715,8 +765,6 @@ cogl_setup_viewport (guint w,
ClutterFixed z_camera; ClutterFixed z_camera;
GE( glViewport (0, 0, width, height) ); GE( glViewport (0, 0, width, height) );
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glLoadIdentity () );
/* For Ortho projection. /* For Ortho projection.
* cogl_wrap_glOrthox (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); * cogl_wrap_glOrthox (0, width << 16, 0, height << 16, -1 << 16, 1 << 16);
@ -724,7 +772,6 @@ cogl_setup_viewport (guint w,
cogl_perspective (fovy, aspect, z_near, z_far); cogl_perspective (fovy, aspect, z_near, z_far);
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( cogl_wrap_glLoadIdentity () ); GE( cogl_wrap_glLoadIdentity () );
/* /*