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
This commit is contained in:
Sjoerd Simons 2014-12-08 11:42:26 +01:00 committed by Ray Strode
parent 00ee03695c
commit 61a26f4216

View file

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