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
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)
{
#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;
}
* @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
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;
* @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);
#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
*