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:
parent
88a561fa01
commit
ef76d8e5e2
60
cogl.h.in
60
cogl.h.in
@ -338,14 +338,35 @@ void cogl_get_bitmasks (gint *red,
|
||||
* @z_near: Nearest visible point
|
||||
* @z_far: Furthest visible point along the z-axis
|
||||
*
|
||||
* Multiplies the current set matrix with a projection matrix based
|
||||
* on the provided values.
|
||||
* Replaces the current projection matrix with a perspective matrix
|
||||
* based on the provided values.
|
||||
*/
|
||||
void cogl_perspective (ClutterFixed fovy,
|
||||
ClutterFixed aspect,
|
||||
ClutterFixed z_near,
|
||||
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:
|
||||
* @width: Width of the viewport
|
||||
@ -369,6 +390,18 @@ void cogl_setup_viewport (guint width,
|
||||
ClutterFixed z_near,
|
||||
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:
|
||||
*
|
||||
@ -511,6 +544,29 @@ void cogl_clip_set (ClutterFixed x_offset,
|
||||
*/
|
||||
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:
|
||||
* @setting: %TRUE to enable depth testing or %FALSE to disable.
|
||||
|
@ -50,6 +50,12 @@ typedef struct _CoglClipStackEntry 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 */
|
||||
ClutterFixed x_offset;
|
||||
ClutterFixed y_offset;
|
||||
@ -61,7 +67,6 @@ struct _CoglClipStackEntry
|
||||
};
|
||||
|
||||
static GList *cogl_clip_stack_top = NULL;
|
||||
static GList *cogl_clip_stack_bottom = NULL;
|
||||
static int cogl_clip_stack_depth = 0;
|
||||
|
||||
static void
|
||||
@ -93,6 +98,7 @@ cogl_clip_set (ClutterFixed x_offset,
|
||||
CoglClipStackEntry *entry = g_slice_new (CoglClipStackEntry);
|
||||
|
||||
/* Make a new entry */
|
||||
entry->clear = FALSE;
|
||||
entry->x_offset = x_offset;
|
||||
entry->y_offset = y_offset;
|
||||
entry->width = width;
|
||||
@ -105,8 +111,6 @@ cogl_clip_set (ClutterFixed x_offset,
|
||||
|
||||
/* Store it in the stack */
|
||||
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
|
||||
@ -118,8 +122,6 @@ cogl_clip_unset (void)
|
||||
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);
|
||||
if (cogl_clip_stack_top == NULL)
|
||||
cogl_clip_stack_bottom = NULL;
|
||||
cogl_clip_stack_depth--;
|
||||
|
||||
/* 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);
|
||||
GList *node;
|
||||
int depth = 1;
|
||||
int depth = 0;
|
||||
|
||||
/* Disable clip planes if the stack is empty */
|
||||
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))
|
||||
_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 */
|
||||
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)
|
||||
{
|
||||
const CoglClipStackEntry *entry = (CoglClipStackEntry *) node->data;
|
||||
@ -156,12 +164,16 @@ _cogl_clip_stack_rebuild (gboolean just_stencil)
|
||||
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
|
||||
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 */
|
||||
if (cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES))
|
||||
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);
|
||||
}
|
||||
|
@ -26,11 +26,6 @@
|
||||
#ifndef __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_merge (void);
|
||||
|
||||
|
@ -13,7 +13,9 @@ CoglPixelFormat
|
||||
CoglBufferTarget
|
||||
<SUBSECTION>
|
||||
cogl_perspective
|
||||
cogl_frustum
|
||||
cogl_setup_viewport
|
||||
cogl_viewport
|
||||
cogl_get_modelview_matrix
|
||||
cogl_get_projection_matrix
|
||||
cogl_get_viewport
|
||||
@ -28,6 +30,8 @@ cogl_rotate
|
||||
<SUBSECTION>
|
||||
cogl_clip_set
|
||||
cogl_clip_unset
|
||||
cogl_clip_stack_save
|
||||
cogl_clip_stack_restore
|
||||
<SUBSECTION>
|
||||
cogl_enable_depth_test
|
||||
cogl_alpha_func
|
||||
|
@ -68,6 +68,7 @@ typedef struct
|
||||
|
||||
/* Relying on glext.h to define these */
|
||||
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
|
||||
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
|
||||
COGL_PFNGLBINDRENDERBUFFEREXTPROC pf_glBindRenderbufferEXT;
|
||||
COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC pf_glRenderbufferStorageEXT;
|
||||
COGL_PFNGLGENFRAMEBUFFERSEXTPROC pf_glGenFramebuffersEXT;
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
/* Expecting EXT functions not to be defined - redirect to pointers in context */
|
||||
#define glGenRenderbuffersEXT ctx->pf_glGenRenderbuffersEXT
|
||||
#define glDeleteRenderbuffersEXT ctx->pf_glDeleteRenderbuffersEXT
|
||||
#define glBindRenderbufferEXT ctx->pf_glBindRenderbufferEXT
|
||||
#define glRenderbufferStorageEXT ctx->pf_glRenderbufferStorageEXT
|
||||
#define glGenFramebuffersEXT ctx->pf_glGenFramebuffersEXT
|
||||
@ -68,6 +69,7 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
||||
CoglTexSliceSpan *y_span;
|
||||
GLuint tex_gl_handle;
|
||||
GLuint fbo_gl_handle;
|
||||
GLuint gl_stencil_handle;
|
||||
GLenum status;
|
||||
|
||||
_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);
|
||||
y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 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 */
|
||||
glGenFramebuffersEXT (1, &fbo_gl_handle);
|
||||
GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo_gl_handle) );
|
||||
GE( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
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 */
|
||||
status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
GE( glDeleteFramebuffersEXT (1, &fbo_gl_handle) );
|
||||
GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
|
||||
return COGL_INVALID_HANDLE;
|
||||
/* Stencil renderbuffers aren't always supported. Try again
|
||||
without the stencil buffer */
|
||||
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) );
|
||||
@ -114,10 +142,11 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
||||
/* Allocate and init a CoglFbo object (store non-wasted size
|
||||
for subsequent blits and viewport setup) */
|
||||
fbo = (CoglFbo*) g_malloc (sizeof (CoglFbo));
|
||||
fbo->ref_count = 1;
|
||||
fbo->width = x_span->size - x_span->waste;
|
||||
fbo->height = y_span->size - y_span->waste;
|
||||
fbo->gl_handle = fbo_gl_handle;
|
||||
fbo->ref_count = 1;
|
||||
fbo->width = x_span->size - x_span->waste;
|
||||
fbo->height = y_span->size - y_span->waste;
|
||||
fbo->gl_handle = fbo_gl_handle;
|
||||
fbo->gl_stencil_handle = gl_stencil_handle;
|
||||
|
||||
COGL_HANDLE_DEBUG_NEW (offscreen, fbo);
|
||||
|
||||
@ -140,7 +169,8 @@ _cogl_offscreen_free (CoglFbo *fbo)
|
||||
|
||||
/* Frees FBO resources but its handle is not
|
||||
released! Do that separately before this! */
|
||||
|
||||
if (fbo->gl_stencil_handle)
|
||||
GE( glDeleteRenderbuffersEXT (1, &fbo->gl_stencil_handle) );
|
||||
GE( glDeleteFramebuffersEXT (1, &fbo->gl_handle) );
|
||||
g_free (fbo);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ typedef struct
|
||||
int width;
|
||||
int height;
|
||||
GLuint gl_handle;
|
||||
GLuint gl_stencil_handle;
|
||||
|
||||
} CoglFbo;
|
||||
|
||||
|
67
gl/cogl.c
67
gl/cogl.c
@ -746,6 +746,9 @@ cogl_perspective (ClutterFixed fovy,
|
||||
|
||||
memset (&m[0], 0, sizeof (m));
|
||||
|
||||
GE( glMatrixMode (GL_PROJECTION) );
|
||||
GE( glLoadIdentity () );
|
||||
|
||||
/*
|
||||
* Based on the original algorithm in perspective():
|
||||
*
|
||||
@ -773,6 +776,8 @@ cogl_perspective (ClutterFixed fovy,
|
||||
|
||||
GE( glMultMatrixf (m) );
|
||||
|
||||
GE( glMatrixMode (GL_MODELVIEW) );
|
||||
|
||||
/* Calculate and store the inverse of the matrix */
|
||||
memset (ctx->inverse_projection, 0, sizeof (GLfloat) * 16);
|
||||
|
||||
@ -786,6 +791,60 @@ cogl_perspective (ClutterFixed fovy,
|
||||
#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
|
||||
cogl_setup_viewport (guint width,
|
||||
guint height,
|
||||
@ -798,12 +857,8 @@ cogl_setup_viewport (guint width,
|
||||
|
||||
GE( glViewport (0, 0, width, height) );
|
||||
|
||||
GE( glMatrixMode (GL_PROJECTION) );
|
||||
GE( glLoadIdentity () );
|
||||
|
||||
cogl_perspective (fovy, aspect, z_near, z_far);
|
||||
|
||||
GE( glMatrixMode (GL_MODELVIEW) );
|
||||
GE( glLoadIdentity () );
|
||||
|
||||
/*
|
||||
@ -969,6 +1024,10 @@ _cogl_features_init ()
|
||||
(COGL_PFNGLGENRENDERBUFFERSEXTPROC)
|
||||
cogl_get_proc_address ("glGenRenderbuffersEXT");
|
||||
|
||||
ctx->pf_glDeleteRenderbuffersEXT =
|
||||
(COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
|
||||
cogl_get_proc_address ("glDeleteRenderbuffersEXT");
|
||||
|
||||
ctx->pf_glBindRenderbufferEXT =
|
||||
(COGL_PFNGLBINDRENDERBUFFEREXTPROC)
|
||||
cogl_get_proc_address ("glBindRenderbufferEXT");
|
||||
|
@ -666,6 +666,31 @@ cogl_wrap_glMultMatrixx (const GLfixed *m)
|
||||
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
|
||||
cogl_wrap_glScalex (GLfixed x, GLfixed y, GLfixed z)
|
||||
{
|
||||
|
@ -204,6 +204,9 @@ void cogl_wrap_glPopMatrix ();
|
||||
void cogl_wrap_glMatrixMode (GLenum mode);
|
||||
void cogl_wrap_glLoadIdentity ();
|
||||
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_glTranslatex (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_glLoadIdentity glLoadIdentity
|
||||
#define cogl_wrap_glMultMatrixx glMultMatrixx
|
||||
#define cogl_wrap_glFrustumx glFrustumx
|
||||
#define cogl_wrap_glScalex glScalex
|
||||
#define cogl_wrap_glTranslatex glTranslatex
|
||||
#define cogl_wrap_glRotatex glRotatex
|
||||
|
55
gles/cogl.c
55
gles/cogl.c
@ -661,7 +661,10 @@ cogl_perspective (ClutterFixed fovy,
|
||||
|
||||
memset (&m[0], 0, sizeof (m));
|
||||
|
||||
/*
|
||||
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
|
||||
GE( cogl_wrap_glLoadIdentity () );
|
||||
|
||||
/*
|
||||
* Based on the original algorithm in perspective():
|
||||
*
|
||||
* 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_glMatrixMode (GL_MODELVIEW) );
|
||||
|
||||
/* Calculate and store the inverse of the matrix */
|
||||
memset (ctx->inverse_projection, 0, sizeof (ClutterFixed) * 16);
|
||||
|
||||
@ -702,6 +707,51 @@ cogl_perspective (ClutterFixed fovy,
|
||||
#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
|
||||
cogl_setup_viewport (guint w,
|
||||
guint h,
|
||||
@ -715,8 +765,6 @@ cogl_setup_viewport (guint w,
|
||||
ClutterFixed z_camera;
|
||||
|
||||
GE( glViewport (0, 0, width, height) );
|
||||
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
|
||||
GE( cogl_wrap_glLoadIdentity () );
|
||||
|
||||
/* For Ortho projection.
|
||||
* 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);
|
||||
|
||||
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
|
||||
GE( cogl_wrap_glLoadIdentity () );
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user