diff options
Diffstat (limited to 'payloads/libpayload')
-rw-r--r-- | payloads/libpayload/drivers/video/graphics.c | 60 | ||||
-rw-r--r-- | payloads/libpayload/include/cbgfx.h | 30 |
2 files changed, 84 insertions, 6 deletions
diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c index bb8467bf80..54d3dfa2b2 100644 --- a/payloads/libpayload/drivers/video/graphics.c +++ b/payloads/libpayload/drivers/video/graphics.c @@ -61,6 +61,37 @@ static const struct vector vzero = { .y = 0, }; +struct blend_value { + uint8_t alpha; + struct rgb_color rgb; +}; + +static struct blend_value blend = { + .alpha = 0, + .rgb.red = 0, + .rgb.green = 0, + .rgb.blue = 0, +}; + +int set_blend(const struct rgb_color *rgb, uint8_t alpha) +{ + if (rgb == NULL) + return CBGFX_ERROR_INVALID_PARAMETER; + + blend.alpha = alpha; + blend.rgb = *rgb; + + return CBGFX_SUCCESS; +} + +void clear_blend(void) +{ + blend.alpha = 0; + blend.rgb.red = 0; + blend.rgb.green = 0; + blend.rgb.blue = 0; +} + static void add_vectors(struct vector *out, const struct vector *v1, const struct vector *v2) { @@ -135,16 +166,33 @@ static int within_box(const struct vector *v, const struct rect *bound) return -1; } +/* + * Helper function that applies color and opacity from blend struct + * into the color. + */ +static inline uint8_t apply_blend(uint8_t color, uint8_t blend_color) +{ + if (blend.alpha == 0 || color == blend_color) + return color; + + return (color * (256 - blend.alpha) + + blend_color * blend.alpha) / 256; +} + static inline uint32_t calculate_color(const struct rgb_color *rgb, uint8_t invert) { uint32_t color = 0; - color |= (rgb->red >> (8 - fbinfo->red_mask_size)) - << fbinfo->red_mask_pos; - color |= (rgb->green >> (8 - fbinfo->green_mask_size)) - << fbinfo->green_mask_pos; - color |= (rgb->blue >> (8 - fbinfo->blue_mask_size)) - << fbinfo->blue_mask_pos; + + color |= (apply_blend(rgb->red, blend.rgb.red) + >> (8 - fbinfo->red_mask_size)) + << fbinfo->red_mask_pos; + color |= (apply_blend(rgb->green, blend.rgb.green) + >> (8 - fbinfo->green_mask_size)) + << fbinfo->green_mask_pos; + color |= (apply_blend(rgb->blue, blend.rgb.blue) + >> (8 - fbinfo->blue_mask_size)) + << fbinfo->blue_mask_pos; if (invert) color ^= 0xffffffff; return color; diff --git a/payloads/libpayload/include/cbgfx.h b/payloads/libpayload/include/cbgfx.h index 869f272722..84e76f26d1 100644 --- a/payloads/libpayload/include/cbgfx.h +++ b/payloads/libpayload/include/cbgfx.h @@ -210,3 +210,33 @@ int draw_bitmap_direct(const void *bitmap, size_t size, * in the original size are returned. */ int get_bitmap_dimension(const void *bitmap, size_t sz, struct scale *dim_rel); + +/** + * Setup alpha and rgb values for alpha blending. When alpha is != 0, + * this enables a translucent layer of color (defined by rgb) to be + * blended at a given translucency (alpha) to all things drawn. Call + * clear_blend() to disable alpha blending. + * + * @param[in] rgb Color for transparency + * @param[in] alpha Opacity of color, from 0-255 where + * 0 = completely transparent (no blending) + * 255 = max alpha argument + * + * @return CBGFX_* error codes + */ +int set_blend(const struct rgb_color *rgb, uint8_t alpha); + +/** + * Clear alpha and rgb values, thus disabling any alpha blending. + * + * @return CBGFX_* error codes + */ +void clear_blend(void); + +/** + * For calculating Alpha value from % opacity + * For reference: + * 255 = max alpha argument + * 0 = min alpha argument, 0% opacity + */ +#define ALPHA(percentage) MIN(255, (256 * percentage / 100)) |