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:
Marco Trevisan (Treviño) 2017-10-28 10:57:26 +02:00 committed by Jonas Ådahl
parent 5d4a804c90
commit 0141fef561
5 changed files with 118 additions and 46 deletions

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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