[PATCH v3 1/7] dm: video: Add damage tracking API
Heinrich Schuchardt
xypron.glpk at gmx.de
Fri Dec 30 21:49:57 CET 2022
On 12/30/22 20:58, Alexander Graf wrote:
> We are going to introduce image damage tracking to fasten up screen
> refresh on large displays. This patch adds damage tracking for up to
> one rectangle of the screen which is typically enough to hold blt or
> text print updates. Callers into this API and a reduced dcache flush
> code path will follow in later patches.
>
> Signed-off-by: Alexander Graf <agraf at csgraf.de>
> Reported-by: Da Xue <da at libre.computer>
>
> ---
>
> v1 -> v2:
>
> - Remove ifdefs
>
> v2 -> v3:
>
> - Adapt Kconfig to DM always
> ---
> drivers/video/Kconfig | 14 ++++++++++++
> drivers/video/video-uclass.c | 41 ++++++++++++++++++++++++++++++++++++
> include/video.h | 29 +++++++++++++++++++++++--
> 3 files changed, 82 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index f539977d9b..e12457c654 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -62,6 +62,20 @@ config VIDEO_COPY
> To use this, your video driver must set @copy_base in
> struct video_uc_plat.
>
> +config VIDEO_DAMAGE
> + bool "Enable damage tracking of frame buffer regions"
> + default y if ARM && !SYS_DCACHE_OFF
> + help
> + On some machines (most ARM), the display frame buffer resides in
> + RAM. To make the display controller pick up screen updates, we
> + have to flush frame buffer contents from CPU caches into RAM which
> + can be a slow operation.
> +
> + This feature adds damage tracking to collect information about regions
> + that received updates. When we want to sync, we then only flush
> + regions of the frame buffer that were modified before, speeding up
> + screen refreshes significantly.
> +
> config BACKLIGHT_PWM
> bool "Generic PWM based Backlight Driver"
> depends on BACKLIGHT && DM_PWM
> diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
> index 0ce376ca3f..48a053841e 100644
> --- a/drivers/video/video-uclass.c
> +++ b/drivers/video/video-uclass.c
> @@ -21,6 +21,8 @@
> #include <dm/device_compat.h>
> #include <dm/device-internal.h>
> #include <dm/uclass-internal.h>
> +#include <linux/types.h>
> +#include <linux/bitmap.h>
> #ifdef CONFIG_SANDBOX
> #include <asm/sdl.h>
> #endif
> @@ -254,6 +256,45 @@ void video_set_default_colors(struct udevice *dev, bool invert)
> priv->colour_bg = video_index_to_colour(priv, back);
> }
>
> +/* Notify about changes in the frame buffer */
> +int video_damage(struct udevice *vid, int x, int y, int width, int height)
> +{
> + struct video_priv *priv = dev_get_uclass_priv(vid);
> + int endx = x + width;
> + int endy = y + height;
> +
> + if (!CONFIG_IS_ENABLED(VIDEO_DAMAGE))
> + return 0;
> +
> + if (x > priv->xsize)
> + return 0;
> +
> + if (y > priv->ysize)
> + return 0;
> +
> + if (endx > priv->xsize)
> + endx = priv->xsize;
> +
> + if (endy > priv->ysize)
> + endy = priv->ysize;
> +
> + if (priv->damage.endx && priv->damage.endy) {
This if is superfluous if you initialize x = priv->xsize, y =
priv->ysize in video_flush_dcache().
Please, simplify the code.
Best regards
Heinrich
> + /* Span a rectangle across all old and new damage */
> + priv->damage.x = min(x, priv->damage.x);
> + priv->damage.y = min(y, priv->damage.y);
> + priv->damage.endx = max(endx, priv->damage.endx);
> + priv->damage.endy = max(endy, priv->damage.endy);
> + } else {
> + /* First damage, setting the rectangle to span it */
> + priv->damage.x = x;
> + priv->damage.y = y;
> + priv->damage.endx = endx;
> + priv->damage.endy = endy;
> + }
> +
> + return 0;
> +}
> +
> /* Flush video activity to the caches */
> int video_sync(struct udevice *vid, bool force)
> {
> diff --git a/include/video.h b/include/video.h
> index 43f2e2c02f..4b35e97f79 100644
> --- a/include/video.h
> +++ b/include/video.h
> @@ -109,6 +109,12 @@ struct video_priv {
> void *fb;
> int fb_size;
> void *copy_fb;
> + struct {
> + int x;
> + int y;
> + int endx;
> + int endy;
> + } damage;
> int line_length;
> u32 colour_fg;
> u32 colour_bg;
> @@ -211,8 +217,9 @@ int video_fill(struct udevice *dev, u32 colour);
> * @return: 0 on success, error code otherwise
> *
> * Some frame buffers are cached or have a secondary frame buffer. This
> - * function syncs these up so that the current contents of the U-Boot frame
> - * buffer are displayed to the user.
> + * function syncs the damaged parts of them up so that the current contents
> + * of the U-Boot frame buffer are displayed to the user. It clears the damage
> + * buffer.
> */
> int video_sync(struct udevice *vid, bool force);
>
> @@ -332,6 +339,24 @@ static inline int video_sync_copy_all(struct udevice *dev)
>
> #endif
>
> +/**
> + * video_damage() - Notify the video subsystem about screen updates.
> + *
> + * @vid: Device to sync
> + * @x: Upper left X coordinate of the damaged rectangle
> + * @y: Upper left Y coordinate of the damaged rectangle
> + * @width: Width of the damaged rectangle
> + * @height: Height of the damaged rectangle
> + *
> + * @return: 0
> + *
> + * Some frame buffers are cached or have a secondary frame buffer. This
> + * function notifies the video subsystem about rectangles that were updated
> + * within the frame buffer. They may only get written to the screen on the
> + * next call to video_sync().
> + */
> +int video_damage(struct udevice *vid, int x, int y, int width, int height);
> +
> /**
> * video_is_active() - Test if one video device it active
> *
More information about the U-Boot
mailing list