summaryrefslogtreecommitdiff
path: root/payloads/libpayload
diff options
context:
space:
mode:
Diffstat (limited to 'payloads/libpayload')
-rw-r--r--payloads/libpayload/drivers/video/graphics.c60
-rw-r--r--payloads/libpayload/include/cbgfx.h30
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))