Add alpha blending to video buffer

calculate-0.9.5
Ray Strode 17 years ago
parent 39dec951a9
commit 166a0b6ef7

@ -36,6 +36,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <values.h>
#include <unistd.h>
#include <linux/fb.h>
@ -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);
}
}

Loading…
Cancel
Save