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
fc73b84002
commit
db4c5e2829
25
ChangeLog
25
ChangeLog
@ -1,3 +1,28 @@
|
||||
2008-08-01 Neil Roberts <neil@o-hand.com>
|
||||
|
||||
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
|
||||
|
||||
2008-08-01 Neil Roberts <neil@o-hand.com>
|
||||
|
||||
Bug 1071 - clutter_timeline_get_duration doesn't always work
|
||||
|
@ -362,8 +362,6 @@ static guint actor_signals[LAST_SIGNAL] = { 0, };
|
||||
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
||||
|
||||
static void _clutter_actor_apply_modelview_transform (ClutterActor *self);
|
||||
static void _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
|
||||
ClutterActor *ancestor);
|
||||
|
||||
static void clutter_actor_shader_pre_paint (ClutterActor *actor,
|
||||
gboolean repeat);
|
||||
@ -1373,7 +1371,7 @@ _clutter_actor_apply_modelview_transform (ClutterActor *self)
|
||||
* This function does not push/pop matrix; it is the responsibility
|
||||
* of the caller to do so as appropriate
|
||||
*/
|
||||
static void
|
||||
void
|
||||
_clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
|
||||
ClutterActor *ancestor)
|
||||
{
|
||||
|
@ -210,6 +210,9 @@ gboolean _clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint,
|
||||
const GValue *handler_return,
|
||||
gpointer dummy);
|
||||
|
||||
void _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
|
||||
ClutterActor *ancestor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
||||
|
@ -430,6 +430,62 @@ clutter_texture_allocate (ClutterActor *self,
|
||||
clutter_actor_allocate_preferred_size (priv->fbo_source, origin_changed);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_texture_set_fbo_projection (ClutterActor *self)
|
||||
{
|
||||
ClutterTexturePrivate *priv = CLUTTER_TEXTURE (self)->priv;
|
||||
ClutterVertex verts[4];
|
||||
ClutterFixed viewport[4];
|
||||
ClutterFixed x_min, x_max, y_min, y_max;
|
||||
ClutterPerspective perspective;
|
||||
ClutterStage *stage;
|
||||
ClutterFixed tan_angle, near_size;
|
||||
int i;
|
||||
|
||||
/* Get the bounding rectangle of the source as drawn in screen
|
||||
coordinates */
|
||||
clutter_actor_get_abs_allocation_vertices (priv->fbo_source, verts);
|
||||
|
||||
x_min = x_max = verts[0].x;
|
||||
y_min = y_max = verts[0].y;
|
||||
|
||||
for (i = 1; i < G_N_ELEMENTS (verts); ++i)
|
||||
{
|
||||
if (verts[i].x < x_min)
|
||||
x_min = verts[i].x;
|
||||
|
||||
if (verts[i].x > x_max)
|
||||
x_max = verts[i].x;
|
||||
|
||||
if (verts[i].y < y_min)
|
||||
y_min = verts[i].y;
|
||||
|
||||
if (verts[i].y > y_max)
|
||||
y_max = verts[i].y;
|
||||
}
|
||||
|
||||
stage = CLUTTER_STAGE (clutter_actor_get_stage (self));
|
||||
clutter_stage_get_perspectivex (stage, &perspective);
|
||||
|
||||
/* Convert the coordinates back to [-1,1] range */
|
||||
cogl_get_viewport (viewport);
|
||||
x_min = CFX_QDIV (x_min, viewport[2]) * 2 - CFX_ONE;
|
||||
x_max = CFX_QDIV (x_max, viewport[2]) * 2 - CFX_ONE;
|
||||
y_min = CFX_QDIV (y_min, viewport[3]) * 2 - CFX_ONE;
|
||||
y_max = CFX_QDIV (y_max, viewport[3]) * 2 - CFX_ONE;
|
||||
|
||||
/* Set up a projection matrix so that the actor will be projected as
|
||||
if it was drawn at its original location */
|
||||
tan_angle = clutter_tani (CLUTTER_ANGLE_FROM_DEGX (perspective.fovy / 2));
|
||||
near_size = CFX_QMUL (perspective.z_near, tan_angle);
|
||||
|
||||
cogl_frustum (CFX_QMUL (x_min, near_size),
|
||||
CFX_QMUL (x_max, near_size),
|
||||
CFX_QMUL (-y_min, near_size),
|
||||
CFX_QMUL (-y_max, near_size),
|
||||
perspective.z_near, perspective.z_far);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_texture_paint (ClutterActor *self)
|
||||
{
|
||||
@ -447,6 +503,8 @@ clutter_texture_paint (ClutterActor *self)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
ClutterShader *shader = NULL;
|
||||
ClutterActor *stage = NULL;
|
||||
ClutterPerspective perspective;
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
|
||||
@ -462,15 +520,52 @@ clutter_texture_paint (ClutterActor *self)
|
||||
/* Redirect drawing to the fbo */
|
||||
cogl_draw_buffer (COGL_OFFSCREEN_BUFFER, priv->fbo_handle);
|
||||
|
||||
if ((stage = clutter_actor_get_stage (self)))
|
||||
{
|
||||
guint stage_width, stage_height;
|
||||
ClutterActor *source_parent;
|
||||
|
||||
clutter_stage_get_perspectivex (CLUTTER_STAGE (stage), &perspective);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
|
||||
/* Use below to set the modelview matrix as if the viewport
|
||||
was still the same size as the stage */
|
||||
cogl_setup_viewport (stage_width, stage_height,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
/* Use a projection matrix that makes the actor appear as it
|
||||
would if it was rendered at its normal screen location */
|
||||
clutter_texture_set_fbo_projection (self);
|
||||
/* Reset the viewport to the size of the FBO */
|
||||
cogl_viewport (priv->width, priv->height);
|
||||
/* Reapply the source's parent transformations */
|
||||
if ((source_parent = clutter_actor_get_parent (priv->fbo_source)))
|
||||
_clutter_actor_apply_modelview_transform_recursive (source_parent,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* cogl_paint_init is called to clear the buffers */
|
||||
cogl_paint_init (&transparent_col);
|
||||
|
||||
/* Clear the clipping stack so that if the FBO actor is being
|
||||
clipped then it won't affect drawing the source */
|
||||
cogl_clip_stack_save ();
|
||||
|
||||
/* Render out actor scene to fbo */
|
||||
clutter_actor_paint (priv->fbo_source);
|
||||
|
||||
cogl_clip_stack_restore ();
|
||||
|
||||
/* Restore drawing to the frame buffer */
|
||||
cogl_draw_buffer (COGL_WINDOW_BUFFER, COGL_INVALID_HANDLE);
|
||||
|
||||
/* Restore the perspective matrix using cogl_perspective so that
|
||||
the inverse matrix will be right */
|
||||
cogl_perspective (perspective.fovy, perspective.aspect,
|
||||
perspective.z_near, perspective.z_far);
|
||||
|
||||
/* If there is a shader on top of the shader stack, turn it back on. */
|
||||
if (shader)
|
||||
clutter_shader_set_is_enabled (shader, TRUE);
|
||||
@ -1600,8 +1695,8 @@ on_fbo_source_size_change (GObject *object,
|
||||
priv->width = w;
|
||||
priv->height = h;
|
||||
|
||||
priv->texture = cogl_texture_new_with_size (priv->width,
|
||||
priv->height,
|
||||
priv->texture = cogl_texture_new_with_size (MAX (priv->width, 1),
|
||||
MAX (priv->height, 1),
|
||||
-1,
|
||||
priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888);
|
||||
@ -1673,6 +1768,21 @@ on_fbo_parent_change (ClutterActor *actor,
|
||||
* adding it to a container.</para>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <para>When getting the image for the clone texture, Clutter
|
||||
* will attempt to render the source actor exactly as it would
|
||||
* appear if it was rendered on screen. The source actor's parent
|
||||
* transformations are taken into account. Therefore if your
|
||||
* source actor is rotated along the X or Y axes so that it has
|
||||
* some depth, the texture will appear differently depending on
|
||||
* the on-screen location of the source actor. While painting the
|
||||
* source actor, Clutter will set up a temporary asymmetric
|
||||
* perspective matrix as the projection matrix so that the source
|
||||
* actor will be projected as if a small section of the screen was
|
||||
* being viewed. Before version 0.8.2, an orthogonal identity
|
||||
* projection was used which meant that the source actor would be
|
||||
* clipped if any part of it was not on the zero Z-plane.</para>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <para>Avoid reparenting the source with the created texture.</para>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
@ -93,21 +95,47 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
||||
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)
|
||||
{
|
||||
/* 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) );
|
||||
|
||||
@ -118,6 +146,7 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -661,6 +661,9 @@ 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():
|
||||
*
|
||||
@ -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 () );
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user