mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -05:00
offscreen-effect: Add clutter_offscreen_effect_get_texture
Sometimes a subclass of ClutterOffscreenEffect wants to paint with a completely custom material. In that case it is awkward to modify the material returned owned by ClutterOffscreenEffect so it makes more sense to just get the texture and manage its own material. Reviewed-by: Emmanuele Bassi <ebassi@linux.intel.com>
This commit is contained in:
parent
0f04a1cd11
commit
041ac40056
@ -78,6 +78,7 @@ struct _ClutterOffscreenEffectPrivate
|
|||||||
{
|
{
|
||||||
CoglHandle offscreen;
|
CoglHandle offscreen;
|
||||||
CoglMaterial *target;
|
CoglMaterial *target;
|
||||||
|
CoglHandle texture;
|
||||||
|
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
@ -85,10 +86,6 @@ struct _ClutterOffscreenEffectPrivate
|
|||||||
gfloat x_offset;
|
gfloat x_offset;
|
||||||
gfloat y_offset;
|
gfloat y_offset;
|
||||||
|
|
||||||
/* The size of the texture */
|
|
||||||
gfloat target_width;
|
|
||||||
gfloat target_height;
|
|
||||||
|
|
||||||
/* This is the calculated size of the fbo before being passed
|
/* This is the calculated size of the fbo before being passed
|
||||||
through create_texture(). This needs to be tracked separately so
|
through create_texture(). This needs to be tracked separately so
|
||||||
that we can detect when a different size is calculated and
|
that we can detect when a different size is calculated and
|
||||||
@ -150,7 +147,6 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
{
|
{
|
||||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||||
CoglHandle texture;
|
|
||||||
|
|
||||||
priv->stage = clutter_actor_get_stage (priv->actor);
|
priv->stage = clutter_actor_get_stage (priv->actor);
|
||||||
if (priv->stage == NULL)
|
if (priv->stage == NULL)
|
||||||
@ -180,20 +176,18 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
COGL_MATERIAL_FILTER_NEAREST);
|
COGL_MATERIAL_FILTER_NEAREST);
|
||||||
}
|
}
|
||||||
|
|
||||||
texture =
|
if (priv->texture != COGL_INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
cogl_handle_unref (priv->texture);
|
||||||
|
priv->texture = COGL_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->texture =
|
||||||
clutter_offscreen_effect_create_texture (self, fbo_width, fbo_height);
|
clutter_offscreen_effect_create_texture (self, fbo_width, fbo_height);
|
||||||
if (texture == COGL_INVALID_HANDLE)
|
if (priv->texture == COGL_INVALID_HANDLE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
cogl_material_set_layer (priv->target, 0, texture);
|
cogl_material_set_layer (priv->target, 0, priv->texture);
|
||||||
cogl_handle_unref (texture);
|
|
||||||
|
|
||||||
/* we need to use the size of the texture target and not the minimum
|
|
||||||
* size we passed to the create_texture() vfunc, as any sub-class might
|
|
||||||
* give use a bigger texture
|
|
||||||
*/
|
|
||||||
priv->target_width = cogl_texture_get_width (texture);
|
|
||||||
priv->target_height = cogl_texture_get_height (texture);
|
|
||||||
|
|
||||||
priv->fbo_width = fbo_width;
|
priv->fbo_width = fbo_width;
|
||||||
priv->fbo_height = fbo_height;
|
priv->fbo_height = fbo_height;
|
||||||
@ -201,7 +195,7 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
if (priv->offscreen != COGL_INVALID_HANDLE)
|
if (priv->offscreen != COGL_INVALID_HANDLE)
|
||||||
cogl_handle_unref (priv->offscreen);
|
cogl_handle_unref (priv->offscreen);
|
||||||
|
|
||||||
priv->offscreen = cogl_offscreen_new_to_texture (texture);
|
priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
|
||||||
if (priv->offscreen == COGL_INVALID_HANDLE)
|
if (priv->offscreen == COGL_INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
|
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
|
||||||
@ -209,8 +203,6 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
cogl_handle_unref (priv->target);
|
cogl_handle_unref (priv->target);
|
||||||
priv->target = COGL_INVALID_HANDLE;
|
priv->target = COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
priv->target_width = 0;
|
|
||||||
priv->target_height = 0;
|
|
||||||
priv->fbo_width = 0;
|
priv->fbo_width = 0;
|
||||||
priv->fbo_height = 0;
|
priv->fbo_height = 0;
|
||||||
|
|
||||||
@ -231,6 +223,7 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
|
|||||||
gfloat fbo_width, fbo_height;
|
gfloat fbo_width, fbo_height;
|
||||||
gfloat width, height;
|
gfloat width, height;
|
||||||
gfloat xexpand, yexpand;
|
gfloat xexpand, yexpand;
|
||||||
|
int texture_width, texture_height;
|
||||||
|
|
||||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -261,6 +254,9 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
|
|||||||
if (!update_fbo (effect, fbo_width, fbo_height))
|
if (!update_fbo (effect, fbo_width, fbo_height))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
texture_width = cogl_texture_get_width (priv->texture);
|
||||||
|
texture_height = cogl_texture_get_height (priv->texture);
|
||||||
|
|
||||||
/* get the current modelview matrix so that we can copy it to the
|
/* get the current modelview matrix so that we can copy it to the
|
||||||
* framebuffer. We also store the matrix that was last used when we
|
* framebuffer. We also store the matrix that was last used when we
|
||||||
* updated the FBO so that we can detect when we don't need to
|
* updated the FBO so that we can detect when we don't need to
|
||||||
@ -284,14 +280,14 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
|
|||||||
xexpand = 0.f;
|
xexpand = 0.f;
|
||||||
if (priv->x_offset < 0.f)
|
if (priv->x_offset < 0.f)
|
||||||
xexpand = -priv->x_offset;
|
xexpand = -priv->x_offset;
|
||||||
if (priv->x_offset + priv->target_width > width)
|
if (priv->x_offset + texture_width > width)
|
||||||
xexpand = MAX (xexpand, (priv->x_offset + priv->target_width) - width);
|
xexpand = MAX (xexpand, (priv->x_offset + texture_width) - width);
|
||||||
|
|
||||||
yexpand = 0.f;
|
yexpand = 0.f;
|
||||||
if (priv->y_offset < 0.f)
|
if (priv->y_offset < 0.f)
|
||||||
yexpand = -priv->y_offset;
|
yexpand = -priv->y_offset;
|
||||||
if (priv->y_offset + priv->target_height > height)
|
if (priv->y_offset + texture_height > height)
|
||||||
yexpand = MAX (yexpand, (priv->y_offset + priv->target_height) - height);
|
yexpand = MAX (yexpand, (priv->y_offset + texture_height) - height);
|
||||||
|
|
||||||
/* Set the viewport */
|
/* Set the viewport */
|
||||||
cogl_set_viewport (-(priv->x_offset + xexpand), -(priv->y_offset + yexpand),
|
cogl_set_viewport (-(priv->x_offset + xexpand), -(priv->y_offset + yexpand),
|
||||||
@ -359,8 +355,8 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect)
|
|||||||
* hadn't been redirected offscreen.
|
* hadn't been redirected offscreen.
|
||||||
*/
|
*/
|
||||||
cogl_rectangle_with_texture_coords (0, 0,
|
cogl_rectangle_with_texture_coords (0, 0,
|
||||||
priv->target_width,
|
cogl_texture_get_width (priv->texture),
|
||||||
priv->target_height,
|
cogl_texture_get_height (priv->texture),
|
||||||
0.0, 0.0,
|
0.0, 0.0,
|
||||||
1.0, 1.0);
|
1.0, 1.0);
|
||||||
}
|
}
|
||||||
@ -448,6 +444,9 @@ clutter_offscreen_effect_finalize (GObject *gobject)
|
|||||||
if (priv->target)
|
if (priv->target)
|
||||||
cogl_handle_unref (priv->target);
|
cogl_handle_unref (priv->target);
|
||||||
|
|
||||||
|
if (priv->texture)
|
||||||
|
cogl_handle_unref (priv->texture);
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject);
|
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,6 +479,35 @@ clutter_offscreen_effect_init (ClutterOffscreenEffect *self)
|
|||||||
ClutterOffscreenEffectPrivate);
|
ClutterOffscreenEffectPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_offscreen_effect_get_texture:
|
||||||
|
* @effect: a #ClutterOffscreenEffect
|
||||||
|
*
|
||||||
|
* Retrieves the texture used as a render target for the offscreen
|
||||||
|
* buffer created by @effect
|
||||||
|
*
|
||||||
|
* You should only use the returned texture when painting. The texture
|
||||||
|
* may change after ClutterEffect::pre_paint is called so the effect
|
||||||
|
* implementation should update any references to the texture after
|
||||||
|
* chaining-up to the parent's pre_paint implementation. This can be
|
||||||
|
* used instead of clutter_offscreen_effect_get_target() when the
|
||||||
|
* effect subclass wants to paint using its own material.
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): a #CoglHandle or %COGL_INVALID_HANDLE. The
|
||||||
|
* returned texture is owned by Clutter and it should not be
|
||||||
|
* modified or freed
|
||||||
|
*
|
||||||
|
* Since: 1.10
|
||||||
|
*/
|
||||||
|
CoglHandle
|
||||||
|
clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect),
|
||||||
|
COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
|
return effect->priv->texture;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_offscreen_effect_get_target:
|
* clutter_offscreen_effect_get_target:
|
||||||
* @effect: a #ClutterOffscreenEffect
|
* @effect: a #ClutterOffscreenEffect
|
||||||
@ -577,14 +605,14 @@ clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
|
|||||||
|
|
||||||
priv = effect->priv;
|
priv = effect->priv;
|
||||||
|
|
||||||
if (priv->target == NULL)
|
if (priv->texture == COGL_INVALID_HANDLE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (width)
|
if (width)
|
||||||
*width = priv->target_width;
|
*width = cogl_texture_get_width (priv->texture);
|
||||||
|
|
||||||
if (height)
|
if (height)
|
||||||
*height = priv->target_height;
|
*height = cogl_texture_get_height (priv->texture);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,8 @@ GType clutter_offscreen_effect_get_type (void) G_GNUC_CONST;
|
|||||||
|
|
||||||
CoglMaterial * clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect);
|
CoglMaterial * clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect);
|
||||||
|
|
||||||
|
CoglHandle clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect);
|
||||||
|
|
||||||
void clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect);
|
void clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect);
|
||||||
CoglHandle clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect,
|
CoglHandle clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect,
|
||||||
gfloat width,
|
gfloat width,
|
||||||
|
@ -2627,6 +2627,7 @@ clutter_effect_get_type
|
|||||||
ClutterOffscreenEffect
|
ClutterOffscreenEffect
|
||||||
ClutterOffscreenEffectClass
|
ClutterOffscreenEffectClass
|
||||||
clutter_offscreen_effect_get_target
|
clutter_offscreen_effect_get_target
|
||||||
|
clutter_offscreen_effect_get_texture
|
||||||
clutter_offscreen_effect_create_texture
|
clutter_offscreen_effect_create_texture
|
||||||
clutter_offscreen_effect_paint_target
|
clutter_offscreen_effect_paint_target
|
||||||
clutter_offscreen_effect_get_target_size
|
clutter_offscreen_effect_get_target_size
|
||||||
|
Loading…
Reference in New Issue
Block a user