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
@ -28,6 +28,7 @@ enum
|
|||||||
PROP_LAYOUT,
|
PROP_LAYOUT,
|
||||||
PROP_FRAMEBUFFER,
|
PROP_FRAMEBUFFER,
|
||||||
PROP_OFFSCREEN,
|
PROP_OFFSCREEN,
|
||||||
|
PROP_SCALE,
|
||||||
|
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
@ -37,6 +38,7 @@ static GParamSpec *obj_props[PROP_LAST];
|
|||||||
typedef struct _ClutterStageViewPrivate
|
typedef struct _ClutterStageViewPrivate
|
||||||
{
|
{
|
||||||
cairo_rectangle_int_t layout;
|
cairo_rectangle_int_t layout;
|
||||||
|
int scale;
|
||||||
CoglFramebuffer *framebuffer;
|
CoglFramebuffer *framebuffer;
|
||||||
|
|
||||||
CoglOffscreen *offscreen;
|
CoglOffscreen *offscreen;
|
||||||
@ -141,6 +143,15 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
|||||||
cogl_framebuffer_pop_matrix (priv->framebuffer);
|
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
|
gboolean
|
||||||
clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
|
clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
|
||||||
{
|
{
|
||||||
@ -229,6 +240,9 @@ clutter_stage_view_get_property (GObject *object,
|
|||||||
case PROP_OFFSCREEN:
|
case PROP_OFFSCREEN:
|
||||||
g_value_set_boxed (value, priv->offscreen);
|
g_value_set_boxed (value, priv->offscreen);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SCALE:
|
||||||
|
g_value_set_int (value, priv->scale);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -257,6 +271,9 @@ clutter_stage_view_set_property (GObject *object,
|
|||||||
case PROP_OFFSCREEN:
|
case PROP_OFFSCREEN:
|
||||||
priv->offscreen = g_value_dup_boxed (value);
|
priv->offscreen = g_value_dup_boxed (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SCALE:
|
||||||
|
priv->scale = g_value_get_int (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
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_viewport = TRUE;
|
||||||
priv->dirty_projection = TRUE;
|
priv->dirty_projection = TRUE;
|
||||||
|
priv->scale = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -323,5 +341,13 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
|||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_STATIC_STRINGS);
|
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);
|
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,
|
void clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
||||||
const cairo_rectangle_int_t *clip);
|
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);
|
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
|
||||||
|
|
||||||
void clutter_stage_view_set_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;
|
gint read_y;
|
||||||
int window_scale;
|
int window_scale;
|
||||||
float fb_width, fb_height;
|
float fb_width, fb_height;
|
||||||
|
int view_scale;
|
||||||
|
int fb_scale;
|
||||||
int viewport_offset_x;
|
int viewport_offset_x;
|
||||||
int viewport_offset_y;
|
int viewport_offset_y;
|
||||||
|
|
||||||
@ -1387,10 +1389,12 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
|
|||||||
|
|
||||||
context = _clutter_context_get_default ();
|
context = _clutter_context_get_default ();
|
||||||
window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
|
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);
|
clutter_stage_view_get_layout (view, &view_layout);
|
||||||
|
|
||||||
fb_width = view_layout.width;
|
fb_width = view_layout.width * view_scale;
|
||||||
fb_height = view_layout.height;
|
fb_height = view_layout.height * view_scale;
|
||||||
cogl_push_framebuffer (fb);
|
cogl_push_framebuffer (fb);
|
||||||
|
|
||||||
/* needed for when a context switch happens */
|
/* 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
|
* picking to not work at all, so setting it the whole framebuffer content
|
||||||
* for now. */
|
* for now. */
|
||||||
cogl_framebuffer_push_scissor_clip (fb, 0, 0,
|
cogl_framebuffer_push_scissor_clip (fb, 0, 0,
|
||||||
view_layout.width,
|
view_layout.width * view_scale,
|
||||||
view_layout.height);
|
view_layout.height * view_scale);
|
||||||
|
|
||||||
_clutter_stage_window_get_dirty_pixel (priv->impl, view, &dirty_x, &dirty_y);
|
_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)))
|
if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (PICK, "Pushing pick scissor clip x: %d, y: %d, 1x1",
|
CLUTTER_NOTE (PICK, "Pushing pick scissor clip x: %d, y: %d, 1x1",
|
||||||
dirty_x * window_scale,
|
dirty_x * fb_scale,
|
||||||
dirty_y * window_scale);
|
dirty_y * fb_scale);
|
||||||
cogl_framebuffer_push_scissor_clip (fb, dirty_x * window_scale, dirty_y * window_scale, 1, 1);
|
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_x = x * fb_scale - dirty_x * fb_scale;
|
||||||
viewport_offset_y = y * window_scale - dirty_y * window_scale;
|
viewport_offset_y = y * fb_scale - dirty_y * fb_scale;
|
||||||
CLUTTER_NOTE (PICK, "Setting viewport to %f, %f, %f, %f",
|
CLUTTER_NOTE (PICK, "Setting viewport to %f, %f, %f, %f",
|
||||||
priv->viewport[0] * window_scale - viewport_offset_x,
|
priv->viewport[0] * fb_scale - viewport_offset_x,
|
||||||
priv->viewport[1] * window_scale - viewport_offset_y,
|
priv->viewport[1] * fb_scale - viewport_offset_y,
|
||||||
priv->viewport[2] * window_scale,
|
priv->viewport[2] * fb_scale,
|
||||||
priv->viewport[3] * window_scale);
|
priv->viewport[3] * fb_scale);
|
||||||
cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x,
|
cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x,
|
||||||
priv->viewport[1] * window_scale - viewport_offset_y,
|
priv->viewport[1] * fb_scale - viewport_offset_y,
|
||||||
priv->viewport[2] * window_scale,
|
priv->viewport[2] * fb_scale,
|
||||||
priv->viewport[3] * window_scale);
|
priv->viewport[3] * fb_scale);
|
||||||
|
|
||||||
read_x = dirty_x * window_scale;
|
read_x = dirty_x * fb_scale;
|
||||||
read_y = dirty_y * window_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,
|
x, y,
|
||||||
view_layout.width, view_layout.height,
|
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_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255);
|
||||||
cogl_clear (&stage_pick_id, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH);
|
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;
|
cairo_rectangle_int_t view_layout;
|
||||||
ClutterPerspective perspective;
|
ClutterPerspective perspective;
|
||||||
int window_scale;
|
int window_scale;
|
||||||
|
int fb_scale;
|
||||||
int viewport_offset_x;
|
int viewport_offset_x;
|
||||||
int viewport_offset_y;
|
int viewport_offset_y;
|
||||||
float z_2d;
|
float z_2d;
|
||||||
@ -3579,14 +3584,15 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
|||||||
priv->viewport[3]);
|
priv->viewport[3]);
|
||||||
|
|
||||||
window_scale = _clutter_stage_window_get_scale_factor (priv->impl);
|
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);
|
clutter_stage_view_get_layout (view, &view_layout);
|
||||||
|
|
||||||
viewport_offset_x = view_layout.x * window_scale;
|
viewport_offset_x = view_layout.x * fb_scale;
|
||||||
viewport_offset_y = view_layout.y * window_scale;
|
viewport_offset_y = view_layout.y * fb_scale;
|
||||||
cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x,
|
cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x,
|
||||||
priv->viewport[1] * window_scale - viewport_offset_y,
|
priv->viewport[1] * fb_scale - viewport_offset_y,
|
||||||
priv->viewport[2] * window_scale,
|
priv->viewport[2] * fb_scale,
|
||||||
priv->viewport[3] * window_scale);
|
priv->viewport[3] * fb_scale);
|
||||||
|
|
||||||
perspective = priv->perspective;
|
perspective = priv->perspective;
|
||||||
|
|
||||||
|
@ -504,6 +504,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
cairo_rectangle_int_t clip_region;
|
cairo_rectangle_int_t clip_region;
|
||||||
gboolean clip_region_empty;
|
gboolean clip_region_empty;
|
||||||
int window_scale;
|
int window_scale;
|
||||||
|
int fb_scale;
|
||||||
|
|
||||||
wrapper = CLUTTER_ACTOR (stage_cogl->wrapper);
|
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;
|
clip_region_empty = may_use_clipped_redraw && clip_region.width == 0;
|
||||||
|
|
||||||
window_scale = _clutter_stage_window_get_scale_factor (stage_window);
|
window_scale = _clutter_stage_window_get_scale_factor (stage_window);
|
||||||
|
fb_scale = window_scale * clutter_stage_view_get_scale (view);
|
||||||
|
|
||||||
swap_with_damage = FALSE;
|
swap_with_damage = FALSE;
|
||||||
if (has_buffer_age)
|
if (has_buffer_age)
|
||||||
@ -628,13 +630,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
|
|
||||||
stage_cogl->using_clipped_redraw = TRUE;
|
stage_cogl->using_clipped_redraw = TRUE;
|
||||||
|
|
||||||
scissor_x = (clip_region.x - view_rect.x) * window_scale;
|
scissor_x = (clip_region.x - view_rect.x) * fb_scale;
|
||||||
scissor_y = (clip_region.y - view_rect.y) * window_scale;
|
scissor_y = (clip_region.y - view_rect.y) * fb_scale;
|
||||||
cogl_framebuffer_push_scissor_clip (fb,
|
cogl_framebuffer_push_scissor_clip (fb,
|
||||||
scissor_x,
|
scissor_x,
|
||||||
scissor_y,
|
scissor_y,
|
||||||
clip_region.width * window_scale,
|
clip_region.width * fb_scale,
|
||||||
clip_region.height * window_scale);
|
clip_region.height * fb_scale);
|
||||||
paint_stage (stage_cogl, view, &clip_region);
|
paint_stage (stage_cogl, view, &clip_region);
|
||||||
cogl_framebuffer_pop_clip (fb);
|
cogl_framebuffer_pop_clip (fb);
|
||||||
|
|
||||||
@ -653,13 +655,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
int scissor_x;
|
int scissor_x;
|
||||||
int scissor_y;
|
int scissor_y;
|
||||||
|
|
||||||
scissor_x = (clip_region.x - view_rect.x) * window_scale;;
|
scissor_x = (clip_region.x - view_rect.x) * fb_scale;;
|
||||||
scissor_y = (clip_region.y - view_rect.y) * window_scale;
|
scissor_y = (clip_region.y - view_rect.y) * fb_scale;
|
||||||
cogl_framebuffer_push_scissor_clip (fb,
|
cogl_framebuffer_push_scissor_clip (fb,
|
||||||
scissor_x,
|
scissor_x,
|
||||||
scissor_y,
|
scissor_y,
|
||||||
clip_region.width * window_scale,
|
clip_region.width * fb_scale,
|
||||||
clip_region.height * window_scale);
|
clip_region.height * fb_scale);
|
||||||
paint_stage (stage_cogl, view, &clip_region);
|
paint_stage (stage_cogl, view, &clip_region);
|
||||||
cogl_framebuffer_pop_clip (fb);
|
cogl_framebuffer_pop_clip (fb);
|
||||||
}
|
}
|
||||||
@ -724,10 +726,10 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
else if (use_clipped_redraw)
|
else if (use_clipped_redraw)
|
||||||
{
|
{
|
||||||
swap_region = (cairo_rectangle_int_t) {
|
swap_region = (cairo_rectangle_int_t) {
|
||||||
.x = (clip_region.x - view_rect.x) * window_scale,
|
.x = (clip_region.x - view_rect.x) * fb_scale,
|
||||||
.y = (clip_region.y - view_rect.y) * window_scale,
|
.y = (clip_region.y - view_rect.y) * fb_scale,
|
||||||
.width = clip_region.width * window_scale,
|
.width = clip_region.width * fb_scale,
|
||||||
.height = clip_region.height * window_scale,
|
.height = clip_region.height * fb_scale,
|
||||||
};
|
};
|
||||||
g_assert (swap_region.width > 0);
|
g_assert (swap_region.width > 0);
|
||||||
do_swap_buffer = TRUE;
|
do_swap_buffer = TRUE;
|
||||||
@ -737,8 +739,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
swap_region = (cairo_rectangle_int_t) {
|
swap_region = (cairo_rectangle_int_t) {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
.width = view_rect.width * window_scale,
|
.width = view_rect.width * fb_scale,
|
||||||
.height = view_rect.height * window_scale,
|
.height = view_rect.height * fb_scale,
|
||||||
};
|
};
|
||||||
do_swap_buffer = TRUE;
|
do_swap_buffer = TRUE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user