From 61a26f421666bdffa735df29b6b46e5ab0819d9e Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Mon, 8 Dec 2014 11:42:26 +0100 Subject: [PATCH] pixel-buffer: Optimize filling with opaque buffers If the source buffer is known to be fully opaque and the fill is done at full opacity, simply memcpy the data row-by-row instead of iterating over every pixel and blending it with the target buffer. This could be optimized more, in the future, in some cases, by memcpy of the entire block instead of row-by-row. https://bugs.freedesktop.org/show_bug.cgi?id=87105 --- src/libply-splash-core/ply-pixel-buffer.c | 69 ++++++++++++++++------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/src/libply-splash-core/ply-pixel-buffer.c b/src/libply-splash-core/ply-pixel-buffer.c index 2ecfb256..120a2eb0 100644 --- a/src/libply-splash-core/ply-pixel-buffer.c +++ b/src/libply-splash-core/ply-pixel-buffer.c @@ -613,6 +613,50 @@ ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer, data, 1.0); } +static void +ply_pixel_buffer_copy_area (ply_pixel_buffer_t *canvas, + ply_pixel_buffer_t *source, + int x, int y, + ply_rectangle_t *cropped_area) +{ + unsigned long row; + + for (row = y; row < y + cropped_area->height; row++) { + memcpy (canvas->bytes + (cropped_area->y + row - y) * canvas->area.width + cropped_area->x, + source->bytes + (row * source->area.width) + x, + cropped_area->width * 4); + } +} + +static void +ply_pixel_buffer_blend_area (ply_pixel_buffer_t *canvas, + ply_pixel_buffer_t *source, + int x, int y, + ply_rectangle_t *cropped_area, + double opacity) +{ + unsigned long row, column; + uint8_t opacity_as_byte = (uint8_t) (opacity * 255.0); + + for (row = y; row < y + cropped_area->height; row++) { + for (column = x; column < x + cropped_area->width; column++) { + uint32_t pixel_value; + + pixel_value = source->bytes[row * source->area.width + column]; + + pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte); + + if ((pixel_value >> 24) == 0x00) + continue; + + ply_pixel_buffer_blend_value_at_pixel (canvas, + cropped_area->x + (column - x), + cropped_area->y + (row - y), + pixel_value); + } + } +} + void ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canvas, ply_pixel_buffer_t *source, @@ -621,8 +665,6 @@ ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canv ply_rectangle_t *clip_area, float opacity) { - unsigned long row, column; - uint8_t opacity_as_byte; ply_rectangle_t cropped_area; unsigned long x; unsigned long y; @@ -645,25 +687,12 @@ ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canv x = cropped_area.x - x_offset; y = cropped_area.y - y_offset; - opacity_as_byte = (uint8_t) (opacity * 255.0); - for (row = y; row < y + cropped_area.height; row++) { - for (column = x; column < x + cropped_area.width; column++) { - uint32_t pixel_value; - - pixel_value = source->bytes[row * source->area.width + column]; - - pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte); - - if ((pixel_value >> 24) == 0x00) - continue; - - ply_pixel_buffer_blend_value_at_pixel (canvas, - cropped_area.x + (column - x), - cropped_area.y + (row - y), - pixel_value); - } - } + if (opacity == 1.0 && ply_pixel_buffer_is_opaque (source)) + ply_pixel_buffer_copy_area (canvas, source, x, y, &cropped_area); + else + ply_pixel_buffer_blend_area (canvas, source, x, y, &cropped_area, + opacity); ply_region_add_rectangle (canvas->updated_areas, &cropped_area); }