clutter: Add ability to scale stage views
This commit adds the ability to set a scale on a scale view. This will cause the content in the stage view to be painted with the given scale, while still keeping the configured layout on the stage. In effect, for a stage view with scale 'n', this means the framebuffer of a given stage will 'n' times larger, keeping the same size on the stage. https://bugzilla.gnome.org/show_bug.cgi?id=777732
This commit is contained in:
parent
0952409de4
commit
63450d69d3
4 changed files with 78 additions and 41 deletions
|
@ -28,6 +28,7 @@ enum
|
|||
PROP_LAYOUT,
|
||||
PROP_FRAMEBUFFER,
|
||||
PROP_OFFSCREEN,
|
||||
PROP_SCALE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
@ -37,6 +38,7 @@ static GParamSpec *obj_props[PROP_LAST];
|
|||
typedef struct _ClutterStageViewPrivate
|
||||
{
|
||||
cairo_rectangle_int_t layout;
|
||||
int scale;
|
||||
CoglFramebuffer *framebuffer;
|
||||
|
||||
CoglOffscreen *offscreen;
|
||||
|
@ -141,6 +143,15 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
|||
cogl_framebuffer_pop_matrix (priv->framebuffer);
|
||||
}
|
||||
|
||||
int
|
||||
clutter_stage_view_get_scale (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
return priv->scale;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
|
||||
{
|
||||
|
@ -229,6 +240,9 @@ clutter_stage_view_get_property (GObject *object,
|
|||
case PROP_OFFSCREEN:
|
||||
g_value_set_boxed (value, priv->offscreen);
|
||||
break;
|
||||
case PROP_SCALE:
|
||||
g_value_set_int (value, priv->scale);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
|
@ -257,6 +271,9 @@ clutter_stage_view_set_property (GObject *object,
|
|||
case PROP_OFFSCREEN:
|
||||
priv->offscreen = g_value_dup_boxed (value);
|
||||
break;
|
||||
case PROP_SCALE:
|
||||
priv->scale = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
|
@ -284,6 +301,7 @@ clutter_stage_view_init (ClutterStageView *view)
|
|||
|
||||
priv->dirty_viewport = TRUE;
|
||||
priv->dirty_projection = TRUE;
|
||||
priv->scale = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -323,5 +341,13 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
|||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_SCALE] =
|
||||
g_param_spec_int ("scale",
|
||||
"View scale",
|
||||
"The view scale",
|
||||
1, G_MAXINT, 1,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ void clutter_stage_view_transform_to_onscreen (ClutterStageView *vie
|
|||
void clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *clip);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
int clutter_stage_view_get_scale (ClutterStageView *view);
|
||||
|
||||
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
|
||||
|
||||
void clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
|
||||
|
|
|
@ -1380,6 +1380,8 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
|
|||
gint read_y;
|
||||
int window_scale;
|
||||
float fb_width, fb_height;
|
||||
int view_scale;
|
||||
int fb_scale;
|
||||
int viewport_offset_x;
|
||||
int viewport_offset_y;
|
||||
|
||||
|
@ -1387,10 +1389,12 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
|
|||
|
||||
context = _clutter_context_get_default ();
|
||||
window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
|
||||
view_scale = clutter_stage_view_get_scale (view);
|
||||
fb_scale = window_scale * view_scale;
|
||||
clutter_stage_view_get_layout (view, &view_layout);
|
||||
|
||||
fb_width = view_layout.width;
|
||||
fb_height = view_layout.height;
|
||||
fb_width = view_layout.width * view_scale;
|
||||
fb_height = view_layout.height * view_scale;
|
||||
cogl_push_framebuffer (fb);
|
||||
|
||||
/* needed for when a context switch happens */
|
||||
|
@ -1400,38 +1404,38 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
|
|||
* picking to not work at all, so setting it the whole framebuffer content
|
||||
* for now. */
|
||||
cogl_framebuffer_push_scissor_clip (fb, 0, 0,
|
||||
view_layout.width,
|
||||
view_layout.height);
|
||||
view_layout.width * view_scale,
|
||||
view_layout.height * view_scale);
|
||||
|
||||
_clutter_stage_window_get_dirty_pixel (priv->impl, view, &dirty_x, &dirty_y);
|
||||
|
||||
if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
|
||||
{
|
||||
CLUTTER_NOTE (PICK, "Pushing pick scissor clip x: %d, y: %d, 1x1",
|
||||
dirty_x * window_scale,
|
||||
dirty_y * window_scale);
|
||||
cogl_framebuffer_push_scissor_clip (fb, dirty_x * window_scale, dirty_y * window_scale, 1, 1);
|
||||
dirty_x * fb_scale,
|
||||
dirty_y * fb_scale);
|
||||
cogl_framebuffer_push_scissor_clip (fb, dirty_x * fb_scale, dirty_y * fb_scale, 1, 1);
|
||||
}
|
||||
|
||||
viewport_offset_x = x * window_scale - dirty_x * window_scale;
|
||||
viewport_offset_y = y * window_scale - dirty_y * window_scale;
|
||||
viewport_offset_x = x * fb_scale - dirty_x * fb_scale;
|
||||
viewport_offset_y = y * fb_scale - dirty_y * fb_scale;
|
||||
CLUTTER_NOTE (PICK, "Setting viewport to %f, %f, %f, %f",
|
||||
priv->viewport[0] * window_scale - viewport_offset_x,
|
||||
priv->viewport[1] * window_scale - viewport_offset_y,
|
||||
priv->viewport[2] * window_scale,
|
||||
priv->viewport[3] * window_scale);
|
||||
cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x,
|
||||
priv->viewport[1] * window_scale - viewport_offset_y,
|
||||
priv->viewport[2] * window_scale,
|
||||
priv->viewport[3] * window_scale);
|
||||
priv->viewport[0] * fb_scale - viewport_offset_x,
|
||||
priv->viewport[1] * fb_scale - viewport_offset_y,
|
||||
priv->viewport[2] * fb_scale,
|
||||
priv->viewport[3] * fb_scale);
|
||||
cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x,
|
||||
priv->viewport[1] * fb_scale - viewport_offset_y,
|
||||
priv->viewport[2] * fb_scale,
|
||||
priv->viewport[3] * fb_scale);
|
||||
|
||||
read_x = dirty_x * window_scale;
|
||||
read_y = dirty_y * window_scale;
|
||||
read_x = dirty_x * fb_scale;
|
||||
read_y = dirty_y * fb_scale;
|
||||
|
||||
CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d",
|
||||
CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d s: %d",
|
||||
x, y,
|
||||
view_layout.width, view_layout.height,
|
||||
view_layout.x, view_layout.y);
|
||||
view_layout.x, view_layout.y, view_scale);
|
||||
|
||||
cogl_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255);
|
||||
cogl_clear (&stage_pick_id, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH);
|
||||
|
@ -3569,6 +3573,7 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
|||
cairo_rectangle_int_t view_layout;
|
||||
ClutterPerspective perspective;
|
||||
int window_scale;
|
||||
int fb_scale;
|
||||
int viewport_offset_x;
|
||||
int viewport_offset_y;
|
||||
float z_2d;
|
||||
|
@ -3579,14 +3584,15 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
|||
priv->viewport[3]);
|
||||
|
||||
window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
|
||||
fb_scale = window_scale * clutter_stage_view_get_scale (view);
|
||||
clutter_stage_view_get_layout (view, &view_layout);
|
||||
|
||||
viewport_offset_x = view_layout.x * window_scale;
|
||||
viewport_offset_y = view_layout.y * window_scale;
|
||||
cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x,
|
||||
priv->viewport[1] * window_scale - viewport_offset_y,
|
||||
priv->viewport[2] * window_scale,
|
||||
priv->viewport[3] * window_scale);
|
||||
viewport_offset_x = view_layout.x * fb_scale;
|
||||
viewport_offset_y = view_layout.y * fb_scale;
|
||||
cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x,
|
||||
priv->viewport[1] * fb_scale - viewport_offset_y,
|
||||
priv->viewport[2] * fb_scale,
|
||||
priv->viewport[3] * fb_scale);
|
||||
|
||||
perspective = priv->perspective;
|
||||
|
||||
|
|
|
@ -504,6 +504,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||
cairo_rectangle_int_t clip_region;
|
||||
gboolean clip_region_empty;
|
||||
int window_scale;
|
||||
int fb_scale;
|
||||
|
||||
wrapper = CLUTTER_ACTOR (stage_cogl->wrapper);
|
||||
|
||||
|
@ -558,6 +559,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||
clip_region_empty = may_use_clipped_redraw && clip_region.width == 0;
|
||||
|
||||
window_scale = _clutter_stage_window_get_scale_factor (stage_window);
|
||||
fb_scale = window_scale * clutter_stage_view_get_scale (view);
|
||||
|
||||
swap_with_damage = FALSE;
|
||||
if (has_buffer_age)
|
||||
|
@ -628,13 +630,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||
|
||||
stage_cogl->using_clipped_redraw = TRUE;
|
||||
|
||||
scissor_x = (clip_region.x - view_rect.x) * window_scale;
|
||||
scissor_y = (clip_region.y - view_rect.y) * window_scale;
|
||||
scissor_x = (clip_region.x - view_rect.x) * fb_scale;
|
||||
scissor_y = (clip_region.y - view_rect.y) * fb_scale;
|
||||
cogl_framebuffer_push_scissor_clip (fb,
|
||||
scissor_x,
|
||||
scissor_y,
|
||||
clip_region.width * window_scale,
|
||||
clip_region.height * window_scale);
|
||||
clip_region.width * fb_scale,
|
||||
clip_region.height * fb_scale);
|
||||
paint_stage (stage_cogl, view, &clip_region);
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
|
||||
|
@ -653,13 +655,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||
int scissor_x;
|
||||
int scissor_y;
|
||||
|
||||
scissor_x = (clip_region.x - view_rect.x) * window_scale;;
|
||||
scissor_y = (clip_region.y - view_rect.y) * window_scale;
|
||||
scissor_x = (clip_region.x - view_rect.x) * fb_scale;;
|
||||
scissor_y = (clip_region.y - view_rect.y) * fb_scale;
|
||||
cogl_framebuffer_push_scissor_clip (fb,
|
||||
scissor_x,
|
||||
scissor_y,
|
||||
clip_region.width * window_scale,
|
||||
clip_region.height * window_scale);
|
||||
clip_region.width * fb_scale,
|
||||
clip_region.height * fb_scale);
|
||||
paint_stage (stage_cogl, view, &clip_region);
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
}
|
||||
|
@ -724,10 +726,10 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||
else if (use_clipped_redraw)
|
||||
{
|
||||
swap_region = (cairo_rectangle_int_t) {
|
||||
.x = (clip_region.x - view_rect.x) * window_scale,
|
||||
.y = (clip_region.y - view_rect.y) * window_scale,
|
||||
.width = clip_region.width * window_scale,
|
||||
.height = clip_region.height * window_scale,
|
||||
.x = (clip_region.x - view_rect.x) * fb_scale,
|
||||
.y = (clip_region.y - view_rect.y) * fb_scale,
|
||||
.width = clip_region.width * fb_scale,
|
||||
.height = clip_region.height * fb_scale,
|
||||
};
|
||||
g_assert (swap_region.width > 0);
|
||||
do_swap_buffer = TRUE;
|
||||
|
@ -737,8 +739,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||
swap_region = (cairo_rectangle_int_t) {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = view_rect.width * window_scale,
|
||||
.height = view_rect.height * window_scale,
|
||||
.width = view_rect.width * fb_scale,
|
||||
.height = view_rect.height * fb_scale,
|
||||
};
|
||||
do_swap_buffer = TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue