mirror of
https://github.com/brl/mutter.git
synced 2024-12-12 14:20:17 +00:00
c0d5af5de5
A new (internal only currently) API, _clutter_actor_queue_clipped_redraw can be used to queue a redraw along with a clip rectangle in actor coordinates. This clip rectangle propagates up to the stage and clutter backend which may optionally use the information to optimize stage redraws. The GLX backend in particular may scissor the next redraw to the clip rectangle and use GLX_MESA_copy_sub_buffer to present the stage subregion. The intention is that any actors that can naturally determine the bounds of updates should queue clipped redraws to reduce the cost of updating small regions of the screen. Notes: » If GLX_MESA_copy_sub_buffer isn't available then the GLX backend ignores any clip rectangles. » queuing multiple clipped redraws will result in the bounding box of each clip rectangle being used. » If a clipped redraw has a height > 300 pixels then it's promoted into a full stage redraw, so that the GPU doesn't end up blocking too long waiting for the vsync to reach the optimal position to avoid tearing. » Note: no empirical data was used to come up with this threshold so we may need to tune this. » Currently only ClutterX11TexturePixmap makes use of this new API. This is done via a new "queue-damage-redraw" signal that is emitted when the pixmap is updated. The default handler queues a clipped redraw with the assumption that the pixmap is being painted as a rectangle covering the actors transformed allocation. If you subclass ClutterX11TexturePixmap and change how it's painted you now also need to override the signal handler and queue your own redraw. Technically this is a semantic break, but it's assumed that no one is currently doing this. This still leaves a few unsolved issues with regards to optimizing sub stage redraws that need to be addressed in further work so this can only be considered a stepping stone a this point: » Because we have no reliable way to determine if the painting of any given actor is being modified any optimizations implemented using _clutter_actor_queue_redraw_with_clip must be overridable by a subclass, and technically must be opt-in for existing classes to avoid a change in semantics. E.g. consider that a user connects to the paint signal for ClutterTexture and paints a circle instead of a rectangle. In this case any original logic to queue clipped redraws would be incorrect. » Currently only the implementation of an actor has enough information with which to queue clipped redraws. E.g. It is not possible for generic code in clutter-actor.c to queue a clipped redraw when hiding an actor because actors have no way to report a "paint box". (remember actors can draw outside their allocation and actors with depth may also be projected outside of their allocation) » The current plan is to add a actor_class->get_paint_cuboid() virtual so actors can report a bounding cube for everything they would draw in their current state and use that to queue clipped redraws against the stage by projecting the paint cube into stage coordinates. » Our heuristics for promoting clipped redraws into full redraws to avoid blocking the GPU while we wait for the vsync need improving: » vsync issues aren't relevant for redirected/composited applications so they should use different heuristics. In this case we instead need to trade off the cost of blitting when using glXCopySubBuffer vs promoting to a full redraw and flipping instead.
87 lines
4.7 KiB
C
87 lines
4.7 KiB
C
#ifndef __CLUTTER_STAGE_WINDOW_H__
|
|
#define __CLUTTER_STAGE_WINDOW_H__
|
|
|
|
#include <clutter/clutter-actor.h>
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
#define CLUTTER_TYPE_STAGE_WINDOW (clutter_stage_window_get_type ())
|
|
#define CLUTTER_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindow))
|
|
#define CLUTTER_IS_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_WINDOW))
|
|
#define CLUTTER_STAGE_WINDOW_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindowIface))
|
|
|
|
typedef struct _ClutterStageWindow ClutterStageWindow; /* dummy */
|
|
typedef struct _ClutterStageWindowIface ClutterStageWindowIface;
|
|
|
|
struct _ClutterStageWindowIface
|
|
{
|
|
GTypeInterface parent_iface;
|
|
|
|
ClutterActor *(* get_wrapper) (ClutterStageWindow *stage_window);
|
|
|
|
void (* set_title) (ClutterStageWindow *stage_window,
|
|
const gchar *title);
|
|
void (* set_fullscreen) (ClutterStageWindow *stage_window,
|
|
gboolean is_fullscreen);
|
|
void (* set_cursor_visible) (ClutterStageWindow *stage_window,
|
|
gboolean cursor_visible);
|
|
void (* set_user_resizable) (ClutterStageWindow *stage_window,
|
|
gboolean is_resizable);
|
|
|
|
gboolean (* realize) (ClutterStageWindow *stage_window);
|
|
void (* unrealize) (ClutterStageWindow *stage_window);
|
|
|
|
void (* show) (ClutterStageWindow *stage_window,
|
|
gboolean do_raise);
|
|
void (* hide) (ClutterStageWindow *stage_window);
|
|
|
|
void (* resize) (ClutterStageWindow *stage_window,
|
|
gint width,
|
|
gint height);
|
|
void (* get_geometry) (ClutterStageWindow *stage_window,
|
|
ClutterGeometry *geometry);
|
|
|
|
int (* get_pending_swaps) (ClutterStageWindow *stage_window);
|
|
|
|
void (* add_redraw_clip) (ClutterStageWindow *stage_window,
|
|
ClutterGeometry *stage_rectangle);
|
|
gboolean (* has_redraw_clips) (ClutterStageWindow *stage_window);
|
|
gboolean (* ignoring_redraw_clips) (ClutterStageWindow *stage_window);
|
|
};
|
|
|
|
GType clutter_stage_window_get_type (void) G_GNUC_CONST;
|
|
|
|
ClutterActor *_clutter_stage_window_get_wrapper (ClutterStageWindow *window);
|
|
|
|
void _clutter_stage_window_set_title (ClutterStageWindow *window,
|
|
const gchar *title);
|
|
void _clutter_stage_window_set_fullscreen (ClutterStageWindow *window,
|
|
gboolean is_fullscreen);
|
|
void _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window,
|
|
gboolean is_visible);
|
|
void _clutter_stage_window_set_user_resizable (ClutterStageWindow *window,
|
|
gboolean is_resizable);
|
|
|
|
gboolean _clutter_stage_window_realize (ClutterStageWindow *window);
|
|
void _clutter_stage_window_unrealize (ClutterStageWindow *window);
|
|
|
|
void _clutter_stage_window_show (ClutterStageWindow *window,
|
|
gboolean do_raise);
|
|
void _clutter_stage_window_hide (ClutterStageWindow *window);
|
|
|
|
void _clutter_stage_window_resize (ClutterStageWindow *window,
|
|
gint width,
|
|
gint height);
|
|
void _clutter_stage_window_get_geometry (ClutterStageWindow *window,
|
|
ClutterGeometry *geometry);
|
|
int _clutter_stage_window_get_pending_swaps (ClutterStageWindow *window);
|
|
|
|
void _clutter_stage_window_add_redraw_clip (ClutterStageWindow *window,
|
|
ClutterGeometry *stage_clip);
|
|
gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window);
|
|
gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window);
|
|
|
|
G_END_DECLS
|
|
|
|
#endif /* __CLUTTER_STAGE_WINDOW_H__ */
|