in src/libguac/display-plan-combine.c [116:197]
static int guac_display_plan_should_combine(const guac_display_plan_operation* op_a,
const guac_display_plan_operation* op_b) {
/* Operations can only be combined within the same layer */
if (op_a->layer != op_b->layer)
return 0;
/* Simulate combination */
guac_rect combined = op_a->dest;
guac_rect_extend(&combined, &op_b->dest);
/* Operations of the same type can be trivially unified under specific
* circumstances */
if (op_a->type == op_b->type) {
switch (op_a->type) {
/* Copy operations can be combined if they are perfectly adjacent
* (exactly share an edge) and copy from the same source layer in
* the same direction */
case GUAC_DISPLAY_PLAN_OPERATION_COPY:
if (op_a->src.layer_rect.layer == op_b->src.layer_rect.layer
&& guac_display_plan_has_common_edge(op_a, op_b)) {
int delta_xa = op_a->dest.left - op_a->src.layer_rect.rect.left;
int delta_ya = op_a->dest.top - op_a->src.layer_rect.rect.top;
int delta_xb = op_b->dest.left - op_b->src.layer_rect.rect.left;
int delta_yb = op_b->dest.top - op_b->src.layer_rect.rect.top;
return delta_xa == delta_xb
&& delta_ya == delta_yb
&& !guac_display_plan_rect_crosses_boundary(&combined);
}
break;
/* Rectangle-drawing operations can be combined if they are
* perfectly adjacent (exactly share an edge) and draw the same
* color */
case GUAC_DISPLAY_PLAN_OPERATION_RECT:
return op_a->src.color == op_b->src.color
&& guac_display_plan_has_common_edge(op_a, op_b)
&& !guac_display_plan_rect_crosses_boundary(&combined);
/* Image-drawing operations can be combined if doing so wouldn't
* exceed the size limits for images (we enforce size limits here
* to promote parallelism) */
case GUAC_DISPLAY_PLAN_OPERATION_IMG:
return !guac_display_plan_rect_crosses_boundary(&combined);
/* Other combinations require more complex logic... (see below) */
default:
break;
}
}
/* Combine if result is still small */
int combined_width = guac_rect_width(&combined);
int combined_height = guac_rect_height(&combined);
if (combined_width <= GUAC_DISPLAY_NEGLIGIBLE_WIDTH && combined_height <= GUAC_DISPLAY_NEGLIGIBLE_HEIGHT)
return 1;
/* Estimate costs of the existing update, new update, and both combined */
int cost_ab = GUAC_DISPLAY_BASE_COST + combined_width * combined_height;
int cost_a = GUAC_DISPLAY_BASE_COST + op_a->dirty_size;
int cost_b = GUAC_DISPLAY_BASE_COST + op_b->dirty_size;
/* Reduce cost if no image data */
if (op_a->type != GUAC_DISPLAY_PLAN_OPERATION_IMG) cost_a /= GUAC_DISPLAY_DATA_FACTOR;
if (op_b->type != GUAC_DISPLAY_PLAN_OPERATION_IMG) cost_b /= GUAC_DISPLAY_DATA_FACTOR;
/* Combine if cost estimate shows benefit or the increase in cost is
* negligible */
if ((cost_ab <= cost_b + cost_a)
|| (cost_ab - cost_a <= cost_a / GUAC_DISPLAY_NEGLIGIBLE_INCREASE)
|| (cost_ab - cost_b <= cost_b / GUAC_DISPLAY_NEGLIGIBLE_INCREASE))
return 1;
/* Otherwise, do not combine */
return 0;
}