static int guac_display_plan_should_combine()

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;

}