shell: Actually make GLSLEffect an effect
A generic, introspectable Shader effect is not only more flexible than a shader actor, it will also make it much easier to turn Lightbox into an actor subclass and replace Tweener with Clutter's own animation support. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/651
This commit is contained in:
parent
ae7ec648b2
commit
007d305736
@ -24,8 +24,8 @@ t = clamp(t, 0.0, 1.0);\n\
|
|||||||
float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
|
float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
|
||||||
cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
|
cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
|
||||||
|
|
||||||
var RadialShaderQuad = GObject.registerClass(
|
var RadialShaderEffect = GObject.registerClass(
|
||||||
class RadialShaderQuad extends Shell.GLSLEffect {
|
class RadialShaderEffect extends Shell.GLSLEffect {
|
||||||
_init(params) {
|
_init(params) {
|
||||||
super._init(params);
|
super._init(params);
|
||||||
|
|
||||||
@ -99,12 +99,13 @@ var Lightbox = class Lightbox {
|
|||||||
this._children = container.get_children();
|
this._children = container.get_children();
|
||||||
this._fadeFactor = params.fadeFactor;
|
this._fadeFactor = params.fadeFactor;
|
||||||
this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect;
|
this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect;
|
||||||
|
|
||||||
|
this.actor = new St.Bin({ reactive: params.inhibitEvents });
|
||||||
|
|
||||||
if (this._radialEffect)
|
if (this._radialEffect)
|
||||||
this.actor = new RadialShaderQuad({ reactive: params.inhibitEvents });
|
this.actor.add_effect(new RadialShaderEffect({ name: 'radial' }));
|
||||||
else
|
else
|
||||||
this.actor = new St.Bin({ opacity: 0,
|
this.actor.set({ opacity: 0, style_class: 'lightbox' });
|
||||||
style_class: 'lightbox',
|
|
||||||
reactive: params.inhibitEvents });
|
|
||||||
|
|
||||||
container.add_actor(this.actor);
|
container.add_actor(this.actor);
|
||||||
this.actor.raise_top();
|
this.actor.raise_top();
|
||||||
@ -155,7 +156,7 @@ var Lightbox = class Lightbox {
|
|||||||
|
|
||||||
Tweener.removeTweens(this.actor);
|
Tweener.removeTweens(this.actor);
|
||||||
if (this._radialEffect) {
|
if (this._radialEffect) {
|
||||||
Tweener.addTween(this.actor,
|
Tweener.addTween(this.actor.get_effect('radial'),
|
||||||
{ brightness: VIGNETTE_BRIGHTNESS,
|
{ brightness: VIGNETTE_BRIGHTNESS,
|
||||||
vignetteSharpness: VIGNETTE_SHARPNESS,
|
vignetteSharpness: VIGNETTE_SHARPNESS,
|
||||||
time: fadeInTime,
|
time: fadeInTime,
|
||||||
@ -186,7 +187,7 @@ var Lightbox = class Lightbox {
|
|||||||
this.shown = false;
|
this.shown = false;
|
||||||
Tweener.removeTweens(this.actor);
|
Tweener.removeTweens(this.actor);
|
||||||
if (this._radialEffect) {
|
if (this._radialEffect) {
|
||||||
Tweener.addTween(this.actor,
|
Tweener.addTween(this.actor.get_effect('radial'),
|
||||||
{ brightness: 1.0,
|
{ brightness: 1.0,
|
||||||
vignetteSharpness: 0.0,
|
vignetteSharpness: 0.0,
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
|
@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:shell-glsl-effect
|
* SECTION:shell-glsl-effect
|
||||||
* @short_description: Draw a rectangle using GLSL
|
* @short_description: An offscreen effect using GLSL
|
||||||
*
|
*
|
||||||
* A #ShellGLSLEffect draws one single rectangle, sized to the allocation
|
* A #ShellGLSLEffect is a #ClutterOffscreenEffect that allows
|
||||||
* box, but allows running custom GLSL to the vertex and fragment
|
* running custom GLSL to the vertex and fragment stages of the
|
||||||
* stages of the graphic pipeline.
|
* graphic pipeline.
|
||||||
*
|
|
||||||
* To ease writing the shader, a single texture layer is also used.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -20,29 +18,65 @@ typedef struct _ShellGLSLEffectPrivate ShellGLSLEffectPrivate;
|
|||||||
struct _ShellGLSLEffectPrivate
|
struct _ShellGLSLEffectPrivate
|
||||||
{
|
{
|
||||||
CoglPipeline *pipeline;
|
CoglPipeline *pipeline;
|
||||||
|
|
||||||
|
gint tex_width;
|
||||||
|
gint tex_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (ShellGLSLEffect, shell_glsl_effect, CLUTTER_TYPE_ACTOR);
|
G_DEFINE_TYPE_WITH_PRIVATE (ShellGLSLEffect, shell_glsl_effect, CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
shell_glsl_effect_get_paint_volume (ClutterActor *actor,
|
shell_glsl_effect_pre_paint (ClutterEffect *effect)
|
||||||
ClutterPaintVolume *volume)
|
|
||||||
{
|
{
|
||||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
ShellGLSLEffect *self = SHELL_GLSL_EFFECT (effect);
|
||||||
|
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||||
|
ShellGLSLEffectPrivate *priv = shell_glsl_effect_get_instance_private (self);
|
||||||
|
ClutterEffectClass *parent_class;
|
||||||
|
CoglHandle texture;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
|
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||||
|
{
|
||||||
|
/* if we don't have support for GLSL shaders then we
|
||||||
|
* forcibly disable the ActorMeta
|
||||||
|
*/
|
||||||
|
g_warning ("Unable to use the ShaderEffect: the graphics hardware "
|
||||||
|
"or the current GL driver does not implement support "
|
||||||
|
"for the GLSL shading language.");
|
||||||
|
clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_class = CLUTTER_EFFECT_CLASS (shell_glsl_effect_parent_class);
|
||||||
|
success = parent_class->pre_paint (effect);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||||
|
priv->tex_width = cogl_texture_get_width (texture);
|
||||||
|
priv->tex_height = cogl_texture_get_height (texture);
|
||||||
|
|
||||||
|
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_glsl_effect_paint (ClutterActor *actor)
|
shell_glsl_effect_paint_target (ClutterOffscreenEffect *effect)
|
||||||
{
|
{
|
||||||
ShellGLSLEffect *self = SHELL_GLSL_EFFECT (actor);
|
ShellGLSLEffect *self = SHELL_GLSL_EFFECT (effect);
|
||||||
ShellGLSLEffectPrivate *priv;
|
ShellGLSLEffectPrivate *priv;
|
||||||
|
ClutterActor *actor;
|
||||||
guint8 paint_opacity;
|
guint8 paint_opacity;
|
||||||
ClutterActorBox box;
|
|
||||||
|
|
||||||
priv = shell_glsl_effect_get_instance_private (self);
|
priv = shell_glsl_effect_get_instance_private (self);
|
||||||
|
|
||||||
|
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||||
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||||
clutter_actor_get_allocation_box (actor, &box);
|
|
||||||
|
|
||||||
cogl_pipeline_set_color4ub (priv->pipeline,
|
cogl_pipeline_set_color4ub (priv->pipeline,
|
||||||
paint_opacity,
|
paint_opacity,
|
||||||
@ -51,8 +85,8 @@ shell_glsl_effect_paint (ClutterActor *actor)
|
|||||||
paint_opacity);
|
paint_opacity);
|
||||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||||
priv->pipeline,
|
priv->pipeline,
|
||||||
box.x1, box.y1,
|
0, 0,
|
||||||
box.x2, box.y2);
|
priv->tex_width, priv->tex_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -64,7 +98,7 @@ shell_glsl_effect_paint (ClutterActor *actor)
|
|||||||
* @code: GLSL code
|
* @code: GLSL code
|
||||||
* @is_replace: wheter Cogl code should be replaced by the custom shader
|
* @is_replace: wheter Cogl code should be replaced by the custom shader
|
||||||
*
|
*
|
||||||
* Adds a GLSL snippet to the pipeline used for drawing the actor texture.
|
* Adds a GLSL snippet to the pipeline used for drawing the effect texture.
|
||||||
* See #CoglSnippet for details.
|
* See #CoglSnippet for details.
|
||||||
*
|
*
|
||||||
* This is only valid inside the a call to the build_pipeline() virtual
|
* This is only valid inside the a call to the build_pipeline() virtual
|
||||||
@ -149,20 +183,23 @@ shell_glsl_effect_constructed (GObject *object)
|
|||||||
|
|
||||||
priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
|
priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
|
||||||
|
|
||||||
cogl_pipeline_set_layer_null_texture (priv->pipeline, 0);
|
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_glsl_effect_class_init (ShellGLSLEffectClass *klass)
|
shell_glsl_effect_class_init (ShellGLSLEffectClass *klass)
|
||||||
{
|
{
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass);
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterOffscreenEffectClass *offscreen_class;
|
||||||
|
|
||||||
|
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||||
|
offscreen_class->paint_target = shell_glsl_effect_paint_target;
|
||||||
|
|
||||||
|
effect_class->pre_paint = shell_glsl_effect_pre_paint;
|
||||||
|
|
||||||
gobject_class->constructed = shell_glsl_effect_constructed;
|
gobject_class->constructed = shell_glsl_effect_constructed;
|
||||||
gobject_class->dispose = shell_glsl_effect_dispose;
|
gobject_class->dispose = shell_glsl_effect_dispose;
|
||||||
|
|
||||||
actor_class->get_paint_volume = shell_glsl_effect_get_paint_volume;
|
|
||||||
actor_class->paint = shell_glsl_effect_paint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,11 +28,11 @@ typedef enum {
|
|||||||
|
|
||||||
#define SHELL_TYPE_GLSL_EFFECT (shell_glsl_effect_get_type ())
|
#define SHELL_TYPE_GLSL_EFFECT (shell_glsl_effect_get_type ())
|
||||||
G_DECLARE_DERIVABLE_TYPE (ShellGLSLEffect, shell_glsl_effect,
|
G_DECLARE_DERIVABLE_TYPE (ShellGLSLEffect, shell_glsl_effect,
|
||||||
SHELL, GLSL_EFFECT, ClutterActor)
|
SHELL, GLSL_EFFECT, ClutterOffscreenEffect)
|
||||||
|
|
||||||
struct _ShellGLSLEffectClass
|
struct _ShellGLSLEffectClass
|
||||||
{
|
{
|
||||||
ClutterActorClass parent_class;
|
ClutterOffscreenEffectClass parent_class;
|
||||||
|
|
||||||
CoglPipeline *base_pipeline;
|
CoglPipeline *base_pipeline;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user