
From: Simon Glass <sjg@chromium.org> Rather than having the truetype driver draw the cursor, make it just return the information needed to draw the cursor. This will make it possible for the normal console to support a cursor too. Add a check for the cursor being entirely within the framebuffer. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/video/console_core.c | 14 +++++--- drivers/video/console_normal.c | 18 ++++++---- drivers/video/console_truetype.c | 42 ++++++++++-------------- drivers/video/vidconsole-uclass.c | 51 +++++++++++++++++++++++++---- drivers/video/vidconsole_internal.h | 14 +++++--- include/video_console.h | 29 +++++++++++++--- 6 files changed, 119 insertions(+), 49 deletions(-) diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c index 575d0bfe2b8..6db42e63ea9 100644 --- a/drivers/video/console_core.c +++ b/drivers/video/console_core.c @@ -160,12 +160,12 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri return ret; } -int cursor_show(void *line, struct video_priv *vid_priv, uint height, +int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv, bool direction) { int step, line_step, pbytes, ret; + void *line, *dst; uint value; - void *dst; ret = check_bpix_support(vid_priv->bpix); if (ret) @@ -180,16 +180,22 @@ int cursor_show(void *line, struct video_priv *vid_priv, uint height, line_step = vid_priv->line_length; } + /* Figure out where to write the cursor in the frame buffer */ + line = vid_priv->fb + curs->y * vid_priv->line_length + + curs->x * VNBYTES(vid_priv->bpix); + value = vid_priv->colour_fg; - for (int row = 0; row < height; row++) { + for (int row = 0; row < curs->height; row++) { dst = line; + for (int col = 0; col < VIDCONSOLE_CURSOR_WIDTH; col++) fill_pixel_and_goto_next(&dst, value, pbytes, step); + line += line_step; } - return ret; + return 0; } int console_probe(struct udevice *dev) diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index 315d3daa5ce..ad7eb4661a4 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -75,17 +75,18 @@ int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) return console_fixed_putc_xy(dev, x_frac, y, cp, priv->fontdata); } -static int __maybe_unused console_set_cursor_visible(struct udevice *dev, - bool visible, uint x, - uint y, uint index) +static __maybe_unused int console_get_cursor_info(struct udevice *dev, + bool visible, uint x, uint y, + uint index) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); struct console_simple_priv *priv = dev_get_priv(dev); struct video_fontdata *fontdata = priv->fontdata; + struct vidconsole_cursor *curs = &vc_priv->curs; int pbytes = VNBYTES(vid_priv->bpix); - void *start; + void *start, *line; /* for now, this is not used outside expo */ if (!IS_ENABLED(CONFIG_EXPO)) @@ -98,7 +99,12 @@ static int __maybe_unused console_set_cursor_visible(struct udevice *dev, x -= 1; start = vid_priv->fb + y * vid_priv->line_length + x * pbytes; - cursor_show(start, vid_priv, vc_priv->y_charsize, NORMAL_DIRECTION); + line = start; + + /* Store line pointer and height in cursor struct */ + curs->x = x; + curs->y = y; + curs->height = vc_priv->y_charsize; return 0; } @@ -116,7 +122,7 @@ struct vidconsole_ops console_ops = { .get_font = console_simple_get_font, .select_font = console_simple_select_font, #ifdef CONFIG_CURSOR - .set_cursor_visible = console_set_cursor_visible, + .get_cursor_info = console_get_cursor_info, #endif }; diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index eedc285903b..eee4ea2e2a9 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -993,33 +993,30 @@ static int truetype_entry_restore(struct udevice *dev, struct abuf *buf) return 0; } -static int truetype_set_cursor_visible(struct udevice *dev, bool visible, - uint x, uint y, uint index) +static int truetype_get_cursor_info(struct udevice *dev, bool visible, + uint x, uint y, uint index) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); - struct udevice *vid = dev->parent; - struct video_priv *vid_priv = dev_get_uclass_priv(vid); struct console_tt_priv *priv = dev_get_priv(dev); - void *line; + struct vidconsole_cursor *curs = &vc_priv->curs; uint height; if (xpl_phase() <= PHASE_SPL) return -ENOSYS; - if (!visible) - return 0; - /* * figure out where to place the cursor. This driver ignores the * passed-in values, since an entry_restore() must have been done before * calling this function. */ - if (index < priv->pos_ptr) - x = VID_TO_PIXEL(priv->pos[index].xpos_frac); - else - x = VID_TO_PIXEL(vc_priv->xcur_frac); - - y = vc_priv->ycur; + if (visible) { + index = priv->pos_ptr; + if (index < priv->pos_ptr) + x = VID_TO_PIXEL(priv->pos[index].xpos_frac); + else + x = VID_TO_PIXEL(vc_priv->xcur_frac); + y = vc_priv->ycur; + } /* Get font height from current font type */ if (priv->cur_fontdata) @@ -1027,16 +1024,13 @@ static int truetype_set_cursor_visible(struct udevice *dev, bool visible, else height = priv->cur_met->font_size; - /* Figure out where to write the cursor in the frame buffer */ - line = vid_priv->fb + y * vid_priv->line_length + - x * VNBYTES(vid_priv->bpix); - - /* Use the shared cursor drawing function */ - cursor_show(line, vid_priv, height, NORMAL_DIRECTION); + /* Store line pointer and height in cursor struct */ + curs->x = x; + curs->y = y; + curs->index = index; + curs->height = height; - video_damage(dev->parent, x, y, VIDCONSOLE_CURSOR_WIDTH, height); - - return video_sync(vid, true); + return 0; } const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep) @@ -1101,7 +1095,7 @@ struct vidconsole_ops console_truetype_ops = { .nominal = truetype_nominal, .entry_save = truetype_entry_save, .entry_restore = truetype_entry_restore, - .set_cursor_visible = truetype_set_cursor_visible + .get_cursor_info = truetype_get_cursor_info, }; U_BOOT_DRIVER(vidconsole_truetype) = { diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 46fd355c05f..479793bc227 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -17,6 +17,7 @@ #include <dm.h> #include <video.h> #include <video_console.h> +#include "vidconsole_internal.h" #include <video_font.h> /* Bitmap font for code page 437 */ #include <linux/ctype.h> @@ -702,21 +703,59 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf) } #ifdef CONFIG_CURSOR -int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, - uint x, uint y, uint index) +int vidconsole_show_cursor(struct udevice *dev, uint x, uint y, uint index) { + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); struct vidconsole_ops *ops = vidconsole_get_ops(dev); + struct vidconsole_cursor *curs = &priv->curs; int ret; - if (ops->set_cursor_visible) { - ret = ops->set_cursor_visible(dev, visible, x, y, index); - if (ret != -ENOSYS) + /* find out where the cursor should be drawn */ + if (ops->get_cursor_info) { + ret = ops->get_cursor_info(dev, true, x, y, index); + if (ret && ret != -ENOSYS) + return ret; + } + + /* If the driver stored cursor line and height, use them for drawing */ + if (curs->height) { + struct udevice *vid = dev_get_parent(dev); + struct video_priv *vid_priv = dev_get_uclass_priv(vid); + + /* + * avoid drawing off the display - we assume that the driver + * ensures that curs->y < vid_priv->ysize + */ + curs->height = min(curs->height, vid_priv->ysize - curs->y); + + ret = cursor_show(curs, vid_priv, NORMAL_DIRECTION); + if (ret) + return ret; + + /* Update display damage for cursor area */ + video_damage(vid, curs->x, curs->y, VIDCONSOLE_CURSOR_WIDTH, + curs->height); + } + + priv->curs.visible = true; + + return 0; +} + +int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, + uint x, uint y, uint index) +{ + if (visible) { + int ret; + + ret = vidconsole_show_cursor(dev, x, y, index); + if (ret) return ret; } return 0; } -#endif +#endif /* CONFIG_CURSOR */ void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, enum colour_idx bg, struct vidconsole_colour *old) diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h index 0654a8f98e6..c008b9cf7d3 100644 --- a/drivers/video/vidconsole_internal.h +++ b/drivers/video/vidconsole_internal.h @@ -9,6 +9,10 @@ #include <charset.h> #include <config.h> +struct udevice; +struct vidconsole_cursor; +struct video_priv; + #define FLIPPED_DIRECTION 1 #define NORMAL_DIRECTION 0 @@ -98,10 +102,10 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri /** * cursor_show() - Draw a simple vertical cursor * - * @line: pointer to framebuffer buffer: upper left cursor corner - * @vid_priv: driver private data - * @height: height of the cursor in pixels - * @param direction controls cursor orientation. Can be normal or flipped. + * @curs: cursor information + * @vid_priv: video-device info + * @direction: controls cursor orientation (normal or flipped) + * * When normal: When flipped: *|-----------------------------------------------| *| * | line stepping | @@ -116,7 +120,7 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri * * Return: 0, if success, or else error code. */ -int cursor_show(void *line, struct video_priv *vid_priv, uint height, +int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv, bool direction); /** diff --git a/include/video_console.h b/include/video_console.h index ba34bb8e19f..d86cac42110 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -330,9 +330,9 @@ struct vidconsole_ops { int (*entry_restore)(struct udevice *dev, struct abuf *buf); /** - * set_cursor_visible() - Show or hide the cursor + * get_cursor_info() - Get cursor position info * - * Shows or hides a cursor at the current position + * Calculates and stores cursor position information * * @dev: Console device to use * @visible: true to show the cursor, false to hide it @@ -341,8 +341,8 @@ struct vidconsole_ops { * @index: Character position (0 = at start) * Return: 0 if OK, -ve on error */ - int (*set_cursor_visible)(struct udevice *dev, bool visible, - uint x, uint y, uint index); + int (*get_cursor_info)(struct udevice *dev, bool visible, + uint x, uint y, uint index); }; /* Get a pointer to the driver operations for a video console device */ @@ -430,6 +430,21 @@ int vidconsole_entry_save(struct udevice *dev, struct abuf *buf); int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf); #ifdef CONFIG_CURSOR +/** + * vidconsole_show_cursor() - Show the cursor + * + * Shows a cursor at the specified position. The position is passed in, but for + * the truetype console it is not actually used, since it tracks where the + * cursor must go. + * + * @dev: Console device to use + * @x: X position in pixels + * @y: Y position in pixels + * @index: Character position (0 = at start) + * Return: 0 if OK, -ve on error + */ +int vidconsole_show_cursor(struct udevice *dev, uint x, uint y, uint index); + /** * vidconsole_set_cursor_visible() - Show or hide the cursor * @@ -445,6 +460,12 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf); int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, uint x, uint y, uint index); #else +static inline int vidconsole_show_cursor(struct udevice *dev, uint x, uint y, + uint index) +{ + return 0; +} + static inline int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, uint x, uint y, uint index) -- 2.43.0