From: Ray Strode Date: Thu, 10 May 2007 16:26:34 +0000 (-0400) Subject: Add alpha blending to video buffer X-Git-Tag: 0.1.0~321 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=166a0b6ef7d1f4a00693c2560786fb0dc8171f5d;p=thirdparty%2Fplymouth.git Add alpha blending to video buffer --- diff --git a/src/ply-video-buffer.c b/src/ply-video-buffer.c index 50294cb1..e15f2523 100644 --- a/src/ply-video-buffer.c +++ b/src/ply-video-buffer.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -81,12 +82,28 @@ static uint32_t ply_video_buffer_convert_color_to_pixel_value ( uint8_t green, uint8_t blue, uint8_t alpha); -static void ply_video_buffer_set_pixel_to_value (PlyVideoBuffer *buffer, +static uint32_t ply_video_buffer_get_value_at_pixel (PlyVideoBuffer *buffer, + int x, + int y); +static void ply_video_buffer_set_value_at_pixel (PlyVideoBuffer *buffer, int x, int y, uint32_t pixel_value); - -static void ply_video_buffer_add_area_to_flush_area (PlyVideoBuffer *buffer, +static void ply_video_buffer_blend_value_at_pixel (PlyVideoBuffer *buffer, + int x, + int y, + uint32_t pixel_value); + +static void ply_video_buffer_set_area_to_pixel_value ( + PlyVideoBuffer *buffer, + PlyVideoBufferArea *area, + uint32_t pixel_value); +static void ply_video_buffer_blend_area_with_pixel_value ( + PlyVideoBuffer *buffer, + PlyVideoBufferArea *area, + uint32_t pixel_value); + +static void ply_video_buffer_add_area_to_flush_area (PlyVideoBuffer *buffer, PlyVideoBufferArea *area); static bool ply_video_buffer_flush (PlyVideoBuffer *buffer); @@ -200,6 +217,51 @@ ply_video_buffer_convert_color_to_pixel_value (PlyVideoBuffer *buffer, pixel_value = (alpha << 24) | (red << 16) | (green << 8) | blue; break; + default: + pixel_value = 0; + assert ((buffer->bytes_per_pixel == 2) + || (buffer->bytes_per_pixel == 3) + || (buffer->bytes_per_pixel == 4)); + break; + } + + return pixel_value; +} + +static uint32_t +ply_video_buffer_get_value_at_pixel (PlyVideoBuffer *buffer, + int x, + int y) +{ + unsigned long bytes_per_row; + unsigned long offset; + uint32_t pixel_value; + + assert (buffer != NULL); + + switch (buffer->bytes_per_pixel) + { + case 2: + pixel_value = + buffer->shadow_layout.for_16bpp[y * buffer->area.width + x]; + break; + + case 3: + bytes_per_row = buffer->bytes_per_pixel * buffer->area.width; + offset = (y * bytes_per_row) + (x * buffer->bytes_per_pixel); + + /* FIXME: I think we're going to need to byteswap pixel_value on + * ppc + */ + memcpy (&pixel_value, buffer->shadow_layout.address + offset, + buffer->bytes_per_pixel); + break; + + case 4: + pixel_value = + buffer->shadow_layout.for_16bpp[y * buffer->area.width + x]; + break; + default: assert ((buffer->bytes_per_pixel == 2) || (buffer->bytes_per_pixel == 3) @@ -211,7 +273,7 @@ ply_video_buffer_convert_color_to_pixel_value (PlyVideoBuffer *buffer, } static void -ply_video_buffer_set_pixel_to_value (PlyVideoBuffer *buffer, +ply_video_buffer_set_value_at_pixel (PlyVideoBuffer *buffer, int x, int y, uint32_t pixel_value) @@ -232,8 +294,7 @@ ply_video_buffer_set_pixel_to_value (PlyVideoBuffer *buffer, bytes_per_row = buffer->bytes_per_pixel * buffer->area.width; offset = (y * bytes_per_row) + (x * buffer->bytes_per_pixel); - /* FIXME: I think we're going to need to byteswap pixel_value on - * ppc + /* FIXME: see fixme in _get_value_at_pixel */ memcpy (buffer->shadow_layout.address + offset, &pixel_value, buffer->bytes_per_pixel); @@ -251,6 +312,80 @@ ply_video_buffer_set_pixel_to_value (PlyVideoBuffer *buffer, } } +static void +ply_video_buffer_blend_value_at_pixel (PlyVideoBuffer *buffer, + int x, + int y, + uint32_t pixel_value) +{ + uint32_t old_pixel_value; + double old_red, old_green, old_blue, old_alpha; + double new_red, new_green, new_blue, new_alpha; + + old_pixel_value = ply_video_buffer_get_value_at_pixel (buffer, x, y); + + old_alpha = old_pixel_value / 255.0; + old_red = old_pixel_value / 255.0; + old_green = old_pixel_value / 255.0; + old_blue = old_pixel_value / 255.0; + + new_alpha = (pixel_value >> 24) / 255.0; + new_red = ((pixel_value >> 16) & 0xff) / 255.0; + new_green = ((pixel_value >> 8) & 0xff) / 255.0; + new_blue = (pixel_value & 0xff) / 255.0; + + new_red = new_red * new_alpha + old_red * old_alpha * (1.0 - new_alpha); + new_green = new_green * new_alpha + old_green * old_alpha * (1.0 - new_alpha); + new_blue = new_blue * new_alpha + old_blue * old_alpha * (1.0 - new_alpha); + new_alpha = new_alpha * (1.0 - old_alpha); + + new_red = CLAMP (new_red * 255.0, 0, 255.0); + new_green = CLAMP (new_green * 255.0, 0, 255.0); + new_blue = CLAMP (new_blue * 255.0, 0, 255.0); + new_alpha = CLAMP (new_alpha * 255.0, 0, 255.0); + + pixel_value = (((uint8_t) new_alpha) << 24) + | (((uint8_t) new_red) << 16) + | (((uint8_t) new_green) << 8) + | ((uint8_t) new_blue); + + ply_video_buffer_set_value_at_pixel (buffer, x, y, pixel_value); +} + +static void +ply_video_buffer_set_area_to_pixel_value (PlyVideoBuffer *buffer, + PlyVideoBufferArea *area, + uint32_t pixel_value) +{ + long row, column; + + for (row = 0; row < area->height; row++) + { + for (column = 0; column < area->width; column++) + { + ply_video_buffer_set_value_at_pixel (buffer, column, row, + pixel_value); + } + } +} + +static void +ply_video_buffer_blend_area_with_pixel_value (PlyVideoBuffer *buffer, + PlyVideoBufferArea *area, + uint32_t pixel_value) +{ + long row, column; + + for (row = 0; row < area->height; row++) + { + for (column = 0; column < area->width; column++) + { + ply_video_buffer_blend_value_at_pixel (buffer, column, row, + pixel_value); + } + } +} + static void ply_video_buffer_add_area_to_flush_area (PlyVideoBuffer *buffer, PlyVideoBufferArea *area) @@ -357,6 +492,7 @@ ply_video_buffer_open (PlyVideoBuffer *buffer) realloc (buffer->shadow_layout.address, buffer->layout_size); memset (buffer->shadow_layout.address, 0, buffer->layout_size); + ply_video_buffer_fill_with_color (buffer, NULL, 0.0, 0.0, 0.0, 1.0); is_open = true; @@ -442,7 +578,6 @@ ply_video_buffer_fill_with_color (PlyVideoBuffer *buffer, double alpha) { uint32_t pixel_value; - long row, column; assert (buffer != NULL); assert (ply_video_buffer_device_is_open (buffer)); @@ -456,14 +591,11 @@ ply_video_buffer_fill_with_color (PlyVideoBuffer *buffer, CLAMP (green * 255.0, 0, 255), CLAMP (blue * 255.0, 0, 255), CLAMP (alpha * 255.0, 0, 255)); - for (row = 0; row < area->height; row++) - { - for (column = 0; column < area->width; column++) - { - ply_video_buffer_set_pixel_to_value (buffer, column, row, - pixel_value); - } - } + + if (abs (alpha - 1.0) <= DBL_MIN) + ply_video_buffer_set_area_to_pixel_value (buffer, area, pixel_value); + else + ply_video_buffer_blend_area_with_pixel_value (buffer, area, pixel_value); ply_video_buffer_add_area_to_flush_area (buffer, area); @@ -504,8 +636,12 @@ ply_video_buffer_fill_with_argb32_data (PlyVideoBuffer *buffer, pixel_value = ply_video_buffer_convert_color_to_pixel_value (buffer, red, green, blue, alpha); - ply_video_buffer_set_pixel_to_value (buffer, column, row, - pixel_value); + if (alpha == 0xff) + ply_video_buffer_set_value_at_pixel (buffer, column, row, + pixel_value); + else + ply_video_buffer_blend_value_at_pixel (buffer, column, row, + pixel_value); } }