diff options
| -rw-r--r-- | drivers/video/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/video/video-uclass.c | 35 | ||||
| -rw-r--r-- | include/video.h | 40 |
3 files changed, 86 insertions, 2 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 73353944971..bc9c7c1d223 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -98,6 +98,19 @@ 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" + 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 c684c994b61..8e2edd7ec49 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -369,6 +369,34 @@ 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 */ +#ifdef CONFIG_VIDEO_DAMAGE +void video_damage(struct udevice *vid, int x, int y, int width, int height) +{ + struct video_priv *priv = dev_get_uclass_priv(vid); + int xend = x + width; + int yend = y + height; + + if (x > priv->xsize) + return; + + if (y > priv->ysize) + return; + + if (xend > priv->xsize) + xend = priv->xsize; + + if (yend > priv->ysize) + yend = priv->ysize; + + /* Span a rectangle across all old and new damage */ + priv->damage.xstart = min(x, priv->damage.xstart); + priv->damage.ystart = min(y, priv->damage.ystart); + priv->damage.xend = max(xend, priv->damage.xend); + priv->damage.yend = max(yend, priv->damage.yend); +} +#endif + /* Flush video activity to the caches */ int video_sync(struct udevice *vid, bool force) { @@ -402,6 +430,13 @@ int video_sync(struct udevice *vid, bool force) #endif priv->last_sync = get_timer(0); + if (IS_ENABLED(CONFIG_VIDEO_DAMAGE)) { + priv->damage.xstart = priv->xsize; + priv->damage.ystart = priv->ysize; + priv->damage.xend = 0; + priv->damage.yend = 0; + } + return 0; } diff --git a/include/video.h b/include/video.h index a1f7fd7e839..7eed112e00c 100644 --- a/include/video.h +++ b/include/video.h @@ -85,6 +85,11 @@ enum video_format { * @fb_size: Frame buffer size * @copy_fb: Copy of the frame buffer to keep up to date; see struct * video_uc_plat + * @damage: A bounding box of framebuffer regions updated since last sync + * @damage.xstart: X start position in pixels from the left + * @damage.ystart: Y start position in pixels from the top + * @damage.xend: X end position in pixels from the left + * @damage.xend: Y end position in pixels from the top * @line_length: Length of each frame buffer line, in bytes. This can be * set by the driver, but if not, the uclass will set it after * probing @@ -113,6 +118,12 @@ struct video_priv { void *fb; int fb_size; void *copy_fb; + struct { + int xstart; + int ystart; + int xend; + int yend; + } damage; int line_length; u32 colour_fg; u32 colour_bg; @@ -259,8 +270,9 @@ int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, * @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); @@ -380,6 +392,30 @@ static inline int video_sync_copy_all(struct udevice *dev) #endif +#ifdef CONFIG_VIDEO_DAMAGE +/** + * 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 + * + * 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(). + */ +void video_damage(struct udevice *vid, int x, int y, int width, int height); +#else +static inline void video_damage(struct udevice *vid, int x, int y, int width, + int height) +{ + return; +} +#endif /* CONFIG_VIDEO_DAMAGE */ + /** * video_is_active() - Test if one video device it active * |
