st-theme-node: Paint elements in resource-scale scaled surfaces
Pass resource-scale to drawing phase, and use it to create texture surfaces scaled with the widget current scaling. Also redraw by default widgets when the resource scale changes. https://bugzilla.gnome.org/show_bug.cgi?id=765011
This commit is contained in:
parent
5d4a804c90
commit
0141fef561
@ -48,6 +48,7 @@ typedef struct {
|
|||||||
guint radius;
|
guint radius;
|
||||||
guint border_width_1;
|
guint border_width_1;
|
||||||
guint border_width_2;
|
guint border_width_2;
|
||||||
|
float resource_scale;
|
||||||
} StCornerSpec;
|
} StCornerSpec;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -78,10 +79,13 @@ create_corner_material (StCornerSpec *corner)
|
|||||||
guint rowstride;
|
guint rowstride;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
guint size;
|
guint size;
|
||||||
|
guint logical_size;
|
||||||
guint max_border_width;
|
guint max_border_width;
|
||||||
|
double device_scaling;
|
||||||
|
|
||||||
max_border_width = MAX(corner->border_width_2, corner->border_width_1);
|
max_border_width = MAX(corner->border_width_2, corner->border_width_1);
|
||||||
size = 2 * MAX(max_border_width, corner->radius);
|
logical_size = 2 * MAX(max_border_width, corner->radius);
|
||||||
|
size = ceilf (logical_size * corner->resource_scale);
|
||||||
rowstride = size * 4;
|
rowstride = size * 4;
|
||||||
data = g_new0 (guint8, size * rowstride);
|
data = g_new0 (guint8, size * rowstride);
|
||||||
|
|
||||||
@ -89,9 +93,11 @@ create_corner_material (StCornerSpec *corner)
|
|||||||
CAIRO_FORMAT_ARGB32,
|
CAIRO_FORMAT_ARGB32,
|
||||||
size, size,
|
size, size,
|
||||||
rowstride);
|
rowstride);
|
||||||
|
device_scaling = (double) size / logical_size;
|
||||||
|
cairo_surface_set_device_scale (surface, device_scaling, device_scaling);
|
||||||
cr = cairo_create (surface);
|
cr = cairo_create (surface);
|
||||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_scale (cr, size, size);
|
cairo_scale (cr, logical_size, logical_size);
|
||||||
|
|
||||||
if (max_border_width <= corner->radius)
|
if (max_border_width <= corner->radius)
|
||||||
{
|
{
|
||||||
@ -189,13 +195,14 @@ create_corner_material (StCornerSpec *corner)
|
|||||||
static char *
|
static char *
|
||||||
corner_to_string (StCornerSpec *corner)
|
corner_to_string (StCornerSpec *corner)
|
||||||
{
|
{
|
||||||
return g_strdup_printf ("st-theme-node-corner:%02x%02x%02x%02x,%02x%02x%02x%02x,%02x%02x%02x%02x,%u,%u,%u",
|
return g_strdup_printf ("st-theme-node-corner:%02x%02x%02x%02x,%02x%02x%02x%02x,%02x%02x%02x%02x,%u,%u,%u,%.4f",
|
||||||
corner->color.red, corner->color.blue, corner->color.green, corner->color.alpha,
|
corner->color.red, corner->color.blue, corner->color.green, corner->color.alpha,
|
||||||
corner->border_color_1.red, corner->border_color_1.green, corner->border_color_1.blue, corner->border_color_1.alpha,
|
corner->border_color_1.red, corner->border_color_1.green, corner->border_color_1.blue, corner->border_color_1.alpha,
|
||||||
corner->border_color_2.red, corner->border_color_2.green, corner->border_color_2.blue, corner->border_color_2.alpha,
|
corner->border_color_2.red, corner->border_color_2.green, corner->border_color_2.blue, corner->border_color_2.alpha,
|
||||||
corner->radius,
|
corner->radius,
|
||||||
corner->border_width_1,
|
corner->border_width_1,
|
||||||
corner->border_width_2);
|
corner->border_width_2,
|
||||||
|
corner->resource_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglTexture *
|
static CoglTexture *
|
||||||
@ -352,6 +359,7 @@ static CoglPipeline *
|
|||||||
st_theme_node_lookup_corner (StThemeNode *node,
|
st_theme_node_lookup_corner (StThemeNode *node,
|
||||||
float width,
|
float width,
|
||||||
float height,
|
float height,
|
||||||
|
float resource_scale,
|
||||||
StCorner corner_id)
|
StCorner corner_id)
|
||||||
{
|
{
|
||||||
CoglTexture *texture = NULL;
|
CoglTexture *texture = NULL;
|
||||||
@ -370,6 +378,7 @@ st_theme_node_lookup_corner (StThemeNode *node,
|
|||||||
|
|
||||||
corner.radius = radius[corner_id];
|
corner.radius = radius[corner_id];
|
||||||
corner.color = node->background_color;
|
corner.color = node->background_color;
|
||||||
|
corner.resource_scale = resource_scale;
|
||||||
st_theme_node_get_corner_border_widths (node, corner_id,
|
st_theme_node_get_corner_border_widths (node, corner_id,
|
||||||
&corner.border_width_1,
|
&corner.border_width_1,
|
||||||
&corner.border_width_2);
|
&corner.border_width_2);
|
||||||
@ -431,7 +440,7 @@ get_background_scale (StThemeNode *node,
|
|||||||
switch (node->background_size)
|
switch (node->background_size)
|
||||||
{
|
{
|
||||||
case ST_BACKGROUND_SIZE_AUTO:
|
case ST_BACKGROUND_SIZE_AUTO:
|
||||||
*scale_w = 1.0;
|
*scale_w = 1.0f;
|
||||||
break;
|
break;
|
||||||
case ST_BACKGROUND_SIZE_CONTAIN:
|
case ST_BACKGROUND_SIZE_CONTAIN:
|
||||||
*scale_w = MIN (painting_area_width / background_image_width,
|
*scale_w = MIN (painting_area_width / background_image_width,
|
||||||
@ -485,6 +494,7 @@ get_background_coordinates (StThemeNode *node,
|
|||||||
static void
|
static void
|
||||||
get_background_position (StThemeNode *self,
|
get_background_position (StThemeNode *self,
|
||||||
const ClutterActorBox *allocation,
|
const ClutterActorBox *allocation,
|
||||||
|
float resource_scale,
|
||||||
ClutterActorBox *result,
|
ClutterActorBox *result,
|
||||||
ClutterActorBox *texture_coords)
|
ClutterActorBox *texture_coords)
|
||||||
{
|
{
|
||||||
@ -497,6 +507,9 @@ get_background_position (StThemeNode *self,
|
|||||||
background_image_width = cogl_texture_get_width (self->background_texture);
|
background_image_width = cogl_texture_get_width (self->background_texture);
|
||||||
background_image_height = cogl_texture_get_height (self->background_texture);
|
background_image_height = cogl_texture_get_height (self->background_texture);
|
||||||
|
|
||||||
|
background_image_width /= resource_scale;
|
||||||
|
background_image_height /= resource_scale;
|
||||||
|
|
||||||
/* get the painting area size */
|
/* get the painting area size */
|
||||||
painting_area_width = allocation->x2 - allocation->x1;
|
painting_area_width = allocation->x2 - allocation->x1;
|
||||||
painting_area_height = allocation->y2 - allocation->y1;
|
painting_area_height = allocation->y2 - allocation->y1;
|
||||||
@ -506,6 +519,7 @@ get_background_position (StThemeNode *self,
|
|||||||
painting_area_width, painting_area_height,
|
painting_area_width, painting_area_height,
|
||||||
background_image_width, background_image_height,
|
background_image_width, background_image_height,
|
||||||
&scale_w, &scale_h);
|
&scale_w, &scale_h);
|
||||||
|
|
||||||
background_image_width *= scale_w;
|
background_image_width *= scale_w;
|
||||||
background_image_height *= scale_h;
|
background_image_height *= scale_h;
|
||||||
|
|
||||||
@ -615,6 +629,7 @@ static cairo_pattern_t *
|
|||||||
create_cairo_pattern_of_background_image (StThemeNode *node,
|
create_cairo_pattern_of_background_image (StThemeNode *node,
|
||||||
float width,
|
float width,
|
||||||
float height,
|
float height,
|
||||||
|
float resource_scale,
|
||||||
gboolean *needs_background_fill)
|
gboolean *needs_background_fill)
|
||||||
{
|
{
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
@ -655,9 +670,11 @@ create_cairo_pattern_of_background_image (StThemeNode *node,
|
|||||||
get_background_scale (node,
|
get_background_scale (node,
|
||||||
width, height,
|
width, height,
|
||||||
background_image_width, background_image_height,
|
background_image_width, background_image_height,
|
||||||
&scale_w, &scale_h);
|
resource_scale, &scale_w, &scale_h);
|
||||||
|
|
||||||
if ((scale_w != 1) || (scale_h != 1))
|
if ((scale_w != 1) || (scale_h != 1))
|
||||||
cairo_matrix_scale (&matrix, 1.0/scale_w, 1.0/scale_h);
|
cairo_matrix_scale (&matrix, 1.0/scale_w, 1.0/scale_h);
|
||||||
|
|
||||||
background_image_width *= scale_w;
|
background_image_width *= scale_w;
|
||||||
background_image_height *= scale_h;
|
background_image_height *= scale_h;
|
||||||
|
|
||||||
@ -966,7 +983,8 @@ paint_inset_box_shadow_to_cairo_context (StThemeNode *node,
|
|||||||
static CoglTexture *
|
static CoglTexture *
|
||||||
st_theme_node_prerender_background (StThemeNode *node,
|
st_theme_node_prerender_background (StThemeNode *node,
|
||||||
float actor_width,
|
float actor_width,
|
||||||
float actor_height)
|
float actor_height,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
ClutterBackend *backend = clutter_get_default_backend ();
|
ClutterBackend *backend = clutter_get_default_backend ();
|
||||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||||
@ -994,6 +1012,8 @@ st_theme_node_prerender_background (StThemeNode *node,
|
|||||||
ClutterActorBox paint_box;
|
ClutterActorBox paint_box;
|
||||||
cairo_path_t *interior_path = NULL;
|
cairo_path_t *interior_path = NULL;
|
||||||
float width, height;
|
float width, height;
|
||||||
|
int texture_width;
|
||||||
|
int texture_height;
|
||||||
|
|
||||||
border_image = st_theme_node_get_border_image (node);
|
border_image = st_theme_node_get_border_image (node);
|
||||||
|
|
||||||
@ -1021,8 +1041,11 @@ st_theme_node_prerender_background (StThemeNode *node,
|
|||||||
width = paint_box.x2 - paint_box.x1;
|
width = paint_box.x2 - paint_box.x1;
|
||||||
height = paint_box.y2 - paint_box.y1;
|
height = paint_box.y2 - paint_box.y1;
|
||||||
|
|
||||||
rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width);
|
texture_width = ceilf (width * resource_scale);
|
||||||
data = g_new0 (guchar, height * rowstride);
|
texture_height = ceilf (height * resource_scale);
|
||||||
|
|
||||||
|
rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, texture_width);
|
||||||
|
data = g_new0 (guchar, texture_height * rowstride);
|
||||||
|
|
||||||
/* We zero initialize the destination memory, so it's fully transparent
|
/* We zero initialize the destination memory, so it's fully transparent
|
||||||
* by default.
|
* by default.
|
||||||
@ -1031,8 +1054,9 @@ st_theme_node_prerender_background (StThemeNode *node,
|
|||||||
|
|
||||||
surface = cairo_image_surface_create_for_data (data,
|
surface = cairo_image_surface_create_for_data (data,
|
||||||
CAIRO_FORMAT_ARGB32,
|
CAIRO_FORMAT_ARGB32,
|
||||||
width, height,
|
texture_width, texture_height,
|
||||||
rowstride);
|
rowstride);
|
||||||
|
cairo_surface_set_device_scale (surface, resource_scale, resource_scale);
|
||||||
cr = cairo_create (surface);
|
cr = cairo_create (surface);
|
||||||
|
|
||||||
/* TODO - support non-uniform border colors */
|
/* TODO - support non-uniform border colors */
|
||||||
@ -1070,7 +1094,9 @@ st_theme_node_prerender_background (StThemeNode *node,
|
|||||||
|
|
||||||
if (background_image != NULL)
|
if (background_image != NULL)
|
||||||
{
|
{
|
||||||
pattern = create_cairo_pattern_of_background_image (node, width, height,
|
pattern = create_cairo_pattern_of_background_image (node,
|
||||||
|
width, height,
|
||||||
|
resource_scale,
|
||||||
&draw_solid_background);
|
&draw_solid_background);
|
||||||
if (shadow_spec && pattern != NULL)
|
if (shadow_spec && pattern != NULL)
|
||||||
draw_background_image_shadow = TRUE;
|
draw_background_image_shadow = TRUE;
|
||||||
@ -1286,7 +1312,8 @@ st_theme_node_prerender_background (StThemeNode *node,
|
|||||||
if (interior_path != NULL)
|
if (interior_path != NULL)
|
||||||
cairo_path_destroy (interior_path);
|
cairo_path_destroy (interior_path);
|
||||||
|
|
||||||
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height,
|
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, texture_width,
|
||||||
|
texture_height,
|
||||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||||
rowstride,
|
rowstride,
|
||||||
data,
|
data,
|
||||||
@ -1424,7 +1451,8 @@ static void
|
|||||||
st_theme_node_render_resources (StThemeNodePaintState *state,
|
st_theme_node_render_resources (StThemeNodePaintState *state,
|
||||||
StThemeNode *node,
|
StThemeNode *node,
|
||||||
float width,
|
float width,
|
||||||
float height)
|
float height,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
gboolean has_border;
|
gboolean has_border;
|
||||||
gboolean has_border_radius;
|
gboolean has_border_radius;
|
||||||
@ -1443,6 +1471,7 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
|
|||||||
st_theme_node_paint_state_set_node (state, node);
|
st_theme_node_paint_state_set_node (state, node);
|
||||||
state->alloc_width = width;
|
state->alloc_width = width;
|
||||||
state->alloc_height = height;
|
state->alloc_height = height;
|
||||||
|
state->resource_scale = resource_scale;
|
||||||
|
|
||||||
_st_theme_node_ensure_background (node);
|
_st_theme_node_ensure_background (node);
|
||||||
_st_theme_node_ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
@ -1488,13 +1517,13 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
state->corner_material[ST_CORNER_TOPLEFT] =
|
state->corner_material[ST_CORNER_TOPLEFT] =
|
||||||
st_theme_node_lookup_corner (node, width, height, ST_CORNER_TOPLEFT);
|
st_theme_node_lookup_corner (node, width, height, resource_scale, ST_CORNER_TOPLEFT);
|
||||||
state->corner_material[ST_CORNER_TOPRIGHT] =
|
state->corner_material[ST_CORNER_TOPRIGHT] =
|
||||||
st_theme_node_lookup_corner (node, width, height, ST_CORNER_TOPRIGHT);
|
st_theme_node_lookup_corner (node, width, height, resource_scale, ST_CORNER_TOPRIGHT);
|
||||||
state->corner_material[ST_CORNER_BOTTOMRIGHT] =
|
state->corner_material[ST_CORNER_BOTTOMRIGHT] =
|
||||||
st_theme_node_lookup_corner (node, width, height, ST_CORNER_BOTTOMRIGHT);
|
st_theme_node_lookup_corner (node, width, height, resource_scale, ST_CORNER_BOTTOMRIGHT);
|
||||||
state->corner_material[ST_CORNER_BOTTOMLEFT] =
|
state->corner_material[ST_CORNER_BOTTOMLEFT] =
|
||||||
st_theme_node_lookup_corner (node, width, height, ST_CORNER_BOTTOMLEFT);
|
st_theme_node_lookup_corner (node, width, height, resource_scale, ST_CORNER_BOTTOMLEFT);
|
||||||
|
|
||||||
/* Use cairo to prerender the node if there is a gradient, or
|
/* Use cairo to prerender the node if there is a gradient, or
|
||||||
* background image with borders and/or rounded corners,
|
* background image with borders and/or rounded corners,
|
||||||
@ -1509,7 +1538,8 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
|
|||||||
|| (has_inset_box_shadow && (has_border || node->background_color.alpha > 0))
|
|| (has_inset_box_shadow && (has_border || node->background_color.alpha > 0))
|
||||||
|| (st_theme_node_get_background_image (node) && (has_border || has_border_radius))
|
|| (st_theme_node_get_background_image (node) && (has_border || has_border_radius))
|
||||||
|| has_large_corners)
|
|| has_large_corners)
|
||||||
state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
|
state->prerendered_texture = st_theme_node_prerender_background (node, width, height,
|
||||||
|
resource_scale);
|
||||||
|
|
||||||
if (state->prerendered_texture)
|
if (state->prerendered_texture)
|
||||||
state->prerendered_pipeline = _st_create_texture_pipeline (state->prerendered_texture);
|
state->prerendered_pipeline = _st_create_texture_pipeline (state->prerendered_texture);
|
||||||
@ -1546,7 +1576,8 @@ static void
|
|||||||
st_theme_node_update_resources (StThemeNodePaintState *state,
|
st_theme_node_update_resources (StThemeNodePaintState *state,
|
||||||
StThemeNode *node,
|
StThemeNode *node,
|
||||||
float width,
|
float width,
|
||||||
float height)
|
float height,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
gboolean had_prerendered_texture = FALSE;
|
gboolean had_prerendered_texture = FALSE;
|
||||||
gboolean had_box_shadow = FALSE;
|
gboolean had_box_shadow = FALSE;
|
||||||
@ -1573,12 +1604,13 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
|
|||||||
st_theme_node_paint_state_set_node (state, node);
|
st_theme_node_paint_state_set_node (state, node);
|
||||||
state->alloc_width = width;
|
state->alloc_width = width;
|
||||||
state->alloc_height = height;
|
state->alloc_height = height;
|
||||||
|
state->resource_scale = resource_scale;
|
||||||
|
|
||||||
box_shadow_spec = st_theme_node_get_box_shadow (node);
|
box_shadow_spec = st_theme_node_get_box_shadow (node);
|
||||||
|
|
||||||
if (had_prerendered_texture)
|
if (had_prerendered_texture)
|
||||||
{
|
{
|
||||||
state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
|
state->prerendered_texture = st_theme_node_prerender_background (node, width, height, resource_scale);
|
||||||
state->prerendered_pipeline = _st_create_texture_pipeline (state->prerendered_texture);
|
state->prerendered_pipeline = _st_create_texture_pipeline (state->prerendered_texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1588,7 +1620,7 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
|
|||||||
for (corner_id = 0; corner_id < 4; corner_id++)
|
for (corner_id = 0; corner_id < 4; corner_id++)
|
||||||
if (state->corner_material[corner_id] == NULL)
|
if (state->corner_material[corner_id] == NULL)
|
||||||
state->corner_material[corner_id] =
|
state->corner_material[corner_id] =
|
||||||
st_theme_node_lookup_corner (node, width, height, corner_id);
|
st_theme_node_lookup_corner (node, width, resource_scale, height, corner_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (had_box_shadow)
|
if (had_box_shadow)
|
||||||
@ -2223,6 +2255,7 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state)
|
|||||||
guint border_radius[4];
|
guint border_radius[4];
|
||||||
int max_borders[4];
|
int max_borders[4];
|
||||||
int center_radius, corner_id;
|
int center_radius, corner_id;
|
||||||
|
int fb_width, fb_height;
|
||||||
CoglTexture *buffer;
|
CoglTexture *buffer;
|
||||||
CoglFramebuffer *offscreen = NULL;
|
CoglFramebuffer *offscreen = NULL;
|
||||||
CoglError *error = NULL;
|
CoglError *error = NULL;
|
||||||
@ -2264,9 +2297,9 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Render offscreen */
|
/* Render offscreen */
|
||||||
buffer = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
|
fb_width = ceilf (state->box_shadow_width * state->resource_scale);
|
||||||
state->box_shadow_width,
|
fb_height = ceilf (state->box_shadow_height * state->resource_scale);
|
||||||
state->box_shadow_height));
|
buffer = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, fb_width, fb_height));
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2277,8 +2310,10 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state)
|
|||||||
ClutterActorBox box = { 0, 0, state->box_shadow_width, state->box_shadow_height};
|
ClutterActorBox box = { 0, 0, state->box_shadow_width, state->box_shadow_height};
|
||||||
|
|
||||||
cogl_framebuffer_orthographic (offscreen, 0, 0,
|
cogl_framebuffer_orthographic (offscreen, 0, 0,
|
||||||
state->box_shadow_width,
|
fb_width, fb_height, 0, 1.0);
|
||||||
state->box_shadow_height, 0, 1.0);
|
cogl_framebuffer_scale (offscreen,
|
||||||
|
state->resource_scale,
|
||||||
|
state->resource_scale, 1);
|
||||||
cogl_framebuffer_clear4f (offscreen, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 0);
|
cogl_framebuffer_clear4f (offscreen, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 0);
|
||||||
|
|
||||||
st_theme_node_paint_borders (state, offscreen, &box, 0xFF);
|
st_theme_node_paint_borders (state, offscreen, &box, 0xFF);
|
||||||
@ -2457,11 +2492,16 @@ static gboolean
|
|||||||
st_theme_node_needs_new_box_shadow_for_size (StThemeNodePaintState *state,
|
st_theme_node_needs_new_box_shadow_for_size (StThemeNodePaintState *state,
|
||||||
StThemeNode *node,
|
StThemeNode *node,
|
||||||
float width,
|
float width,
|
||||||
float height)
|
float height,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
if (!node->rendered_once)
|
if (!node->rendered_once)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* The resource scale changed, so need to recompute a new box-shadow */
|
||||||
|
if (fabsf (state->resource_scale - resource_scale) > FLT_EPSILON)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
/* The allocation hasn't changed, no need to recompute a new
|
/* The allocation hasn't changed, no need to recompute a new
|
||||||
box-shadow. */
|
box-shadow. */
|
||||||
if (state->alloc_width == width &&
|
if (state->alloc_width == width &&
|
||||||
@ -2495,7 +2535,8 @@ st_theme_node_paint (StThemeNode *node,
|
|||||||
StThemeNodePaintState *state,
|
StThemeNodePaintState *state,
|
||||||
CoglFramebuffer *framebuffer,
|
CoglFramebuffer *framebuffer,
|
||||||
const ClutterActorBox *box,
|
const ClutterActorBox *box,
|
||||||
guint8 paint_opacity)
|
guint8 paint_opacity,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
float width, height;
|
float width, height;
|
||||||
ClutterActorBox allocation;
|
ClutterActorBox allocation;
|
||||||
@ -2507,7 +2548,7 @@ st_theme_node_paint (StThemeNode *node,
|
|||||||
allocation.x2 = width;
|
allocation.x2 = width;
|
||||||
allocation.y2 = height;
|
allocation.y2 = height;
|
||||||
|
|
||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0 || resource_scale <= 0.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Check whether we need to recreate the textures of the paint
|
/* Check whether we need to recreate the textures of the paint
|
||||||
@ -2516,22 +2557,25 @@ st_theme_node_paint (StThemeNode *node,
|
|||||||
* 2) the allocation size change requires recreating textures
|
* 2) the allocation size change requires recreating textures
|
||||||
*/
|
*/
|
||||||
if (state->node != node ||
|
if (state->node != node ||
|
||||||
st_theme_node_needs_new_box_shadow_for_size (state, node, width, height))
|
st_theme_node_needs_new_box_shadow_for_size (state, node, width, height,
|
||||||
|
resource_scale))
|
||||||
{
|
{
|
||||||
/* If we had the ability to cache textures on the node, then we
|
/* If we had the ability to cache textures on the node, then we
|
||||||
can just copy them over to the paint state and avoid all
|
can just copy them over to the paint state and avoid all
|
||||||
rendering. We end up sharing textures a cross different
|
rendering. We end up sharing textures a cross different
|
||||||
widgets. */
|
widgets. */
|
||||||
if (node->rendered_once && node->cached_textures &&
|
if (node->rendered_once && node->cached_textures &&
|
||||||
width >= node->box_shadow_min_width && height >= node->box_shadow_min_height)
|
width >= node->box_shadow_min_width && height >= node->box_shadow_min_height &&
|
||||||
|
fabsf (resource_scale - state->resource_scale) < FLT_EPSILON)
|
||||||
st_theme_node_paint_state_copy (state, &node->cached_state);
|
st_theme_node_paint_state_copy (state, &node->cached_state);
|
||||||
else
|
else
|
||||||
st_theme_node_render_resources (state, node, width, height);
|
st_theme_node_render_resources (state, node, width, height, resource_scale);
|
||||||
|
|
||||||
node->rendered_once = TRUE;
|
node->rendered_once = TRUE;
|
||||||
}
|
}
|
||||||
else if (state->alloc_width != width || state->alloc_height != height)
|
else if (state->alloc_width != width || state->alloc_height != height ||
|
||||||
st_theme_node_update_resources (state, node, width, height);
|
fabsf (state->resource_scale - resource_scale) > FLT_EPSILON)
|
||||||
|
st_theme_node_update_resources (state, node, width, height, resource_scale);
|
||||||
|
|
||||||
/* Rough notes about the relationship of borders and backgrounds in CSS3;
|
/* Rough notes about the relationship of borders and backgrounds in CSS3;
|
||||||
* see http://www.w3.org/TR/css3-background/ for more accurate details.
|
* see http://www.w3.org/TR/css3-background/ for more accurate details.
|
||||||
@ -2616,7 +2660,8 @@ st_theme_node_paint (StThemeNode *node,
|
|||||||
*/
|
*/
|
||||||
has_visible_outline = st_theme_node_has_visible_outline (node);
|
has_visible_outline = st_theme_node_has_visible_outline (node);
|
||||||
|
|
||||||
get_background_position (node, &allocation, &background_box, &texture_coords);
|
get_background_position (node, &allocation, resource_scale,
|
||||||
|
&background_box, &texture_coords);
|
||||||
|
|
||||||
if (has_visible_outline || node->background_repeat)
|
if (has_visible_outline || node->background_repeat)
|
||||||
cogl_framebuffer_push_rectangle_clip (framebuffer,
|
cogl_framebuffer_push_rectangle_clip (framebuffer,
|
||||||
@ -2707,6 +2752,7 @@ st_theme_node_paint_state_init (StThemeNodePaintState *state)
|
|||||||
|
|
||||||
state->alloc_width = 0;
|
state->alloc_width = 0;
|
||||||
state->alloc_height = 0;
|
state->alloc_height = 0;
|
||||||
|
state->resource_scale = -1;
|
||||||
state->node = NULL;
|
state->node = NULL;
|
||||||
state->box_shadow_pipeline = NULL;
|
state->box_shadow_pipeline = NULL;
|
||||||
state->prerendered_texture = NULL;
|
state->prerendered_texture = NULL;
|
||||||
@ -2731,6 +2777,7 @@ st_theme_node_paint_state_copy (StThemeNodePaintState *state,
|
|||||||
|
|
||||||
state->alloc_width = other->alloc_width;
|
state->alloc_width = other->alloc_width;
|
||||||
state->alloc_height = other->alloc_height;
|
state->alloc_height = other->alloc_height;
|
||||||
|
state->resource_scale = other->resource_scale;
|
||||||
state->box_shadow_width = other->box_shadow_width;
|
state->box_shadow_width = other->box_shadow_width;
|
||||||
state->box_shadow_height = other->box_shadow_height;
|
state->box_shadow_height = other->box_shadow_height;
|
||||||
|
|
||||||
@ -2750,6 +2797,7 @@ st_theme_node_paint_state_invalidate (StThemeNodePaintState *state)
|
|||||||
{
|
{
|
||||||
state->alloc_width = 0;
|
state->alloc_width = 0;
|
||||||
state->alloc_height = 0;
|
state->alloc_height = 0;
|
||||||
|
state->resource_scale = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "st-theme-node-transition.h"
|
#include "st-theme-node-transition.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -237,7 +239,8 @@ st_theme_node_transition_get_paint_box (StThemeNodeTransition *transition,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
setup_framebuffers (StThemeNodeTransition *transition,
|
setup_framebuffers (StThemeNodeTransition *transition,
|
||||||
const ClutterActorBox *allocation)
|
const ClutterActorBox *allocation,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
StThemeNodeTransitionPrivate *priv = transition->priv;
|
StThemeNodeTransitionPrivate *priv = transition->priv;
|
||||||
CoglContext *ctx;
|
CoglContext *ctx;
|
||||||
@ -248,8 +251,8 @@ setup_framebuffers (StThemeNodeTransition *transition,
|
|||||||
static CoglPipeline *material_template = NULL;
|
static CoglPipeline *material_template = NULL;
|
||||||
|
|
||||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||||
width = priv->offscreen_box.x2 - priv->offscreen_box.x1;
|
width = ceilf ((priv->offscreen_box.x2 - priv->offscreen_box.x1) * resource_scale);
|
||||||
height = priv->offscreen_box.y2 - priv->offscreen_box.y1;
|
height = ceilf ((priv->offscreen_box.y2 - priv->offscreen_box.y1) * resource_scale);
|
||||||
|
|
||||||
g_return_val_if_fail (width > 0, FALSE);
|
g_return_val_if_fail (width > 0, FALSE);
|
||||||
g_return_val_if_fail (height > 0, FALSE);
|
g_return_val_if_fail (height > 0, FALSE);
|
||||||
@ -320,7 +323,7 @@ setup_framebuffers (StThemeNodeTransition *transition,
|
|||||||
priv->offscreen_box.y2, 0.0, 1.0);
|
priv->offscreen_box.y2, 0.0, 1.0);
|
||||||
|
|
||||||
st_theme_node_paint (priv->old_theme_node, &priv->old_paint_state,
|
st_theme_node_paint (priv->old_theme_node, &priv->old_paint_state,
|
||||||
priv->old_offscreen, allocation, 255);
|
priv->old_offscreen, allocation, 255, resource_scale);
|
||||||
|
|
||||||
cogl_framebuffer_clear4f (priv->new_offscreen, COGL_BUFFER_BIT_COLOR,
|
cogl_framebuffer_clear4f (priv->new_offscreen, COGL_BUFFER_BIT_COLOR,
|
||||||
0, 0, 0, 0);
|
0, 0, 0, 0);
|
||||||
@ -330,7 +333,7 @@ setup_framebuffers (StThemeNodeTransition *transition,
|
|||||||
priv->offscreen_box.x2,
|
priv->offscreen_box.x2,
|
||||||
priv->offscreen_box.y2, 0.0, 1.0);
|
priv->offscreen_box.y2, 0.0, 1.0);
|
||||||
st_theme_node_paint (priv->new_theme_node, &priv->new_paint_state,
|
st_theme_node_paint (priv->new_theme_node, &priv->new_paint_state,
|
||||||
priv->new_offscreen, allocation, 255);
|
priv->new_offscreen, allocation, 255, resource_scale);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -339,7 +342,8 @@ void
|
|||||||
st_theme_node_transition_paint (StThemeNodeTransition *transition,
|
st_theme_node_transition_paint (StThemeNodeTransition *transition,
|
||||||
CoglFramebuffer *framebuffer,
|
CoglFramebuffer *framebuffer,
|
||||||
ClutterActorBox *allocation,
|
ClutterActorBox *allocation,
|
||||||
guint8 paint_opacity)
|
guint8 paint_opacity,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
StThemeNodeTransitionPrivate *priv = transition->priv;
|
StThemeNodeTransitionPrivate *priv = transition->priv;
|
||||||
|
|
||||||
@ -360,7 +364,8 @@ st_theme_node_transition_paint (StThemeNodeTransition *transition,
|
|||||||
priv->last_allocation = *allocation;
|
priv->last_allocation = *allocation;
|
||||||
|
|
||||||
calculate_offscreen_box (transition, allocation);
|
calculate_offscreen_box (transition, allocation);
|
||||||
priv->needs_setup = !setup_framebuffers (transition, allocation);
|
priv->needs_setup = !setup_framebuffers (transition, allocation,
|
||||||
|
resource_scale);
|
||||||
|
|
||||||
if (priv->needs_setup) /* setting up framebuffers failed */
|
if (priv->needs_setup) /* setting up framebuffers failed */
|
||||||
return;
|
return;
|
||||||
|
@ -43,7 +43,8 @@ void st_theme_node_transition_update (StThemeNodeTransition *transition,
|
|||||||
void st_theme_node_transition_paint (StThemeNodeTransition *transition,
|
void st_theme_node_transition_paint (StThemeNodeTransition *transition,
|
||||||
CoglFramebuffer *framebuffer,
|
CoglFramebuffer *framebuffer,
|
||||||
ClutterActorBox *allocation,
|
ClutterActorBox *allocation,
|
||||||
guint8 paint_opacity);
|
guint8 paint_opacity,
|
||||||
|
float resource_scale);
|
||||||
|
|
||||||
void st_theme_node_transition_get_paint_box (StThemeNodeTransition *transition,
|
void st_theme_node_transition_get_paint_box (StThemeNodeTransition *transition,
|
||||||
const ClutterActorBox *allocation,
|
const ClutterActorBox *allocation,
|
||||||
|
@ -104,6 +104,8 @@ struct _StThemeNodePaintState {
|
|||||||
float box_shadow_width;
|
float box_shadow_width;
|
||||||
float box_shadow_height;
|
float box_shadow_height;
|
||||||
|
|
||||||
|
float resource_scale;
|
||||||
|
|
||||||
CoglPipeline *box_shadow_pipeline;
|
CoglPipeline *box_shadow_pipeline;
|
||||||
CoglPipeline *prerendered_texture;
|
CoglPipeline *prerendered_texture;
|
||||||
CoglPipeline *prerendered_pipeline;
|
CoglPipeline *prerendered_pipeline;
|
||||||
@ -279,7 +281,8 @@ void st_theme_node_paint (StThemeNode *node,
|
|||||||
StThemeNodePaintState *state,
|
StThemeNodePaintState *state,
|
||||||
CoglFramebuffer *framebuffer,
|
CoglFramebuffer *framebuffer,
|
||||||
const ClutterActorBox *box,
|
const ClutterActorBox *box,
|
||||||
guint8 paint_opacity);
|
guint8 paint_opacity,
|
||||||
|
float resource_scale);
|
||||||
|
|
||||||
void st_theme_node_invalidate_background_image (StThemeNode *node);
|
void st_theme_node_invalidate_background_image (StThemeNode *node);
|
||||||
void st_theme_node_invalidate_border_image (StThemeNode *node);
|
void st_theme_node_invalidate_border_image (StThemeNode *node);
|
||||||
|
@ -418,8 +418,12 @@ st_widget_paint_background (StWidget *widget)
|
|||||||
CoglFramebuffer *framebuffer;
|
CoglFramebuffer *framebuffer;
|
||||||
StThemeNode *theme_node;
|
StThemeNode *theme_node;
|
||||||
ClutterActorBox allocation;
|
ClutterActorBox allocation;
|
||||||
|
float resource_scale;
|
||||||
guint8 opacity;
|
guint8 opacity;
|
||||||
|
|
||||||
|
if (!st_widget_get_resource_scale (widget, &resource_scale))
|
||||||
|
return;
|
||||||
|
|
||||||
framebuffer = cogl_get_draw_framebuffer ();
|
framebuffer = cogl_get_draw_framebuffer ();
|
||||||
theme_node = st_widget_get_theme_node (widget);
|
theme_node = st_widget_get_theme_node (widget);
|
||||||
|
|
||||||
@ -431,13 +435,15 @@ st_widget_paint_background (StWidget *widget)
|
|||||||
st_theme_node_transition_paint (priv->transition_animation,
|
st_theme_node_transition_paint (priv->transition_animation,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
&allocation,
|
&allocation,
|
||||||
opacity);
|
opacity,
|
||||||
|
resource_scale);
|
||||||
else
|
else
|
||||||
st_theme_node_paint (theme_node,
|
st_theme_node_paint (theme_node,
|
||||||
current_paint_state (widget),
|
current_paint_state (widget),
|
||||||
framebuffer,
|
framebuffer,
|
||||||
&allocation,
|
&allocation,
|
||||||
opacity);
|
opacity,
|
||||||
|
resource_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1495,7 +1501,16 @@ st_widget_resource_scale_notify (StWidget *widget,
|
|||||||
GParamSpec *pspec,
|
GParamSpec *pspec,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
|
StWidgetPrivate *priv = st_widget_get_instance_private (widget);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
|
||||||
|
st_theme_node_paint_state_invalidate (&priv->paint_states[i]);
|
||||||
|
|
||||||
g_signal_emit (widget, signals[RESOURCE_SCALE_CHANGED], 0);
|
g_signal_emit (widget, signals[RESOURCE_SCALE_CHANGED], 0);
|
||||||
|
|
||||||
|
if (clutter_actor_is_mapped (CLUTTER_ACTOR (widget)))
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user