summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--payloads/libpayload/drivers/video/graphics.c39
-rw-r--r--payloads/libpayload/include/cbgfx.h23
2 files changed, 61 insertions, 1 deletions
diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c
index 2d2ea030ba..2bf5e19d88 100644
--- a/payloads/libpayload/drivers/video/graphics.c
+++ b/payloads/libpayload/drivers/video/graphics.c
@@ -41,6 +41,8 @@
static struct rect canvas;
static struct rect screen;
+static uint8_t *gfx_buffer;
+
/*
* Framebuffer is assumed to assign a higher coordinate (larger x, y) to
* a higher address
@@ -48,7 +50,8 @@ static struct rect screen;
static const struct cb_framebuffer *fbinfo;
/* Shorthand for up-to-date virtual framebuffer address */
-#define FB ((unsigned char *)phys_to_virt(fbinfo->physical_address))
+#define REAL_FB ((unsigned char *)phys_to_virt(fbinfo->physical_address))
+#define FB (gfx_buffer ? gfx_buffer : REAL_FB)
#define LOG(x...) printf("CBGFX: " x)
#define PIVOT_H_MASK (PIVOT_H_LEFT|PIVOT_H_CENTER|PIVOT_H_RIGHT)
@@ -1257,3 +1260,37 @@ int get_bitmap_dimension(const void *bitmap, size_t sz, struct scale *dim_rel)
return CBGFX_SUCCESS;
}
+
+int enable_graphics_buffer(void)
+{
+ if (gfx_buffer)
+ return CBGFX_SUCCESS;
+
+ if (cbgfx_init())
+ return CBGFX_ERROR_INIT;
+
+ size_t buffer_size = fbinfo->y_resolution * fbinfo->bytes_per_line;
+ gfx_buffer = malloc(buffer_size);
+ if (!gfx_buffer) {
+ LOG("%s: Failed to create graphics buffer (%zu bytes).\n",
+ __func__, buffer_size);
+ return CBGFX_ERROR_GRAPHICS_BUFFER;
+ }
+
+ return CBGFX_SUCCESS;
+}
+
+int flush_graphics_buffer(void)
+{
+ if (!gfx_buffer)
+ return CBGFX_ERROR_GRAPHICS_BUFFER;
+
+ memcpy(REAL_FB, gfx_buffer, fbinfo->y_resolution * fbinfo->bytes_per_line);
+ return CBGFX_SUCCESS;
+}
+
+void disable_graphics_buffer(void)
+{
+ free(gfx_buffer);
+ gfx_buffer = NULL;
+}
diff --git a/payloads/libpayload/include/cbgfx.h b/payloads/libpayload/include/cbgfx.h
index 85b61a7b10..72e512267a 100644
--- a/payloads/libpayload/include/cbgfx.h
+++ b/payloads/libpayload/include/cbgfx.h
@@ -56,6 +56,8 @@
#define CBGFX_ERROR_FRAMEBUFFER_ADDR 0x15
/* portrait screen not supported */
#define CBGFX_ERROR_PORTRAIT_SCREEN 0x16
+/* cannot use buffered I/O */
+#define CBGFX_ERROR_GRAPHICS_BUFFER 0x17
struct fraction {
int32_t n;
@@ -272,3 +274,24 @@ void clear_blend(void);
* 0 = min alpha argument, 0% opacity
*/
#define ALPHA(percentage) MIN(255, (256 * percentage / 100))
+
+/**
+ * Enable buffered I/O. All CBGFX operations will be redirected to a working
+ * buffer, and only updated (redrawn) when flush_graphics_buffer() is called.
+ *
+ * @return CBGFX_* error codes
+ */
+int enable_graphics_buffer(void);
+
+/**
+ * Redraw buffered graphics data to real screen if graphics buffer is already
+ * enabled.
+ *
+ * @return CBGFX_* error codes
+ */
+int flush_graphics_buffer(void);
+
+/**
+ * Stop using buffered I/O and release allocated memory.
+ */
+void disable_graphics_buffer(void);