libpayload: cbgfx: Support buffered I/O
For payloads with UI based on CBGFX, they usually start by calling clear_canvas or clear_screen and then draw the UI elements. However, that makes the screen flicker. A typical solution is to identify and minimize the area to redraw. However for payloads with complicated UI and do not care about latency, an alternative is to enable buffered I/O. The new enable_graphics_buffer() will redirect all graphics I/O into an invisible working buffer. To flush (redraw) the buffer to the real screen, call flush_graphics_buffer(). To stop buffering, call disable_graphics_buffer(). BUG=None TEST=Add the enable, flush and disable calls to payload 'depthcharge', built a firmware and boots into Chrome OS recover UI. No more flickering. The average rendering time on x86 platform is 1.2ms. Change-Id: Id60a2824fd9e164feae16b92b68b003beabea8d3 Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44654 Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
6d7996439f
commit
d04b388381
|
@ -41,6 +41,8 @@
|
||||||
static struct rect canvas;
|
static struct rect canvas;
|
||||||
static struct rect screen;
|
static struct rect screen;
|
||||||
|
|
||||||
|
static uint8_t *gfx_buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Framebuffer is assumed to assign a higher coordinate (larger x, y) to
|
* Framebuffer is assumed to assign a higher coordinate (larger x, y) to
|
||||||
* a higher address
|
* a higher address
|
||||||
|
@ -48,7 +50,8 @@ static struct rect screen;
|
||||||
static const struct cb_framebuffer *fbinfo;
|
static const struct cb_framebuffer *fbinfo;
|
||||||
|
|
||||||
/* Shorthand for up-to-date virtual framebuffer address */
|
/* 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 LOG(x...) printf("CBGFX: " x)
|
||||||
#define PIVOT_H_MASK (PIVOT_H_LEFT|PIVOT_H_CENTER|PIVOT_H_RIGHT)
|
#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;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
#define CBGFX_ERROR_FRAMEBUFFER_ADDR 0x15
|
#define CBGFX_ERROR_FRAMEBUFFER_ADDR 0x15
|
||||||
/* portrait screen not supported */
|
/* portrait screen not supported */
|
||||||
#define CBGFX_ERROR_PORTRAIT_SCREEN 0x16
|
#define CBGFX_ERROR_PORTRAIT_SCREEN 0x16
|
||||||
|
/* cannot use buffered I/O */
|
||||||
|
#define CBGFX_ERROR_GRAPHICS_BUFFER 0x17
|
||||||
|
|
||||||
struct fraction {
|
struct fraction {
|
||||||
int32_t n;
|
int32_t n;
|
||||||
|
@ -272,3 +274,24 @@ void clear_blend(void);
|
||||||
* 0 = min alpha argument, 0% opacity
|
* 0 = min alpha argument, 0% opacity
|
||||||
*/
|
*/
|
||||||
#define ALPHA(percentage) MIN(255, (256 * percentage / 100))
|
#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);
|
||||||
|
|
Loading…
Reference in New Issue