Add a new struct vmw_du_update_plane similar to vmw_kms_dirty which
represent the flow of operations needed to update a display unit from
surface or bo (blit a new framebuffer).

v2:
- Kernel doc correction.
- Rebase.

Signed-off-by: Deepak Rawat <dra...@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |  99 ++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 125 ++++++++++++++++++++++++++++
 2 files changed, 224 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 292e48feba83..8a0b31f1b89b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -30,6 +30,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_rect.h>
+#include <drm/drm_damage_helper.h>
 
 /* Might need a hrtimer here? */
 #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
@@ -3092,3 +3093,101 @@ void vmw_kms_lost_device(struct drm_device *dev)
 {
        drm_atomic_helper_shutdown(dev);
 }
+
+/**
+ * vmw_du_helper_plane_update - Helper to do plane update on a display unit.
+ * @update: The closure structure.
+ *
+ * Call this helper after setting callbacks in &vmw_du_update_plane to do plane
+ * update on display unit.
+ *
+ * RETURNS: 0 on success or a negative error code on failure.
+ */
+int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)
+{
+       struct drm_plane_state *state = update->plane->state;
+       struct drm_plane_state *old_state = update->old_state;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       struct drm_rect bb;
+       uint32_t reserved_size = 0;
+       uint32_t submit_size = 0;
+       uint32_t curr_size = 0;
+       uint32_t num_hits = 0;
+       void *cmd_start;
+       char *cmd_next;
+       int ret;
+
+       /*
+        * Iterate in advance to check if really need plane update and find the
+        * number of clips that actually are in plane src for fifo allocation.
+        */
+       drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       if (num_hits == 0)
+               return 0;
+
+       ret = update->prepare(update);
+       if (ret) {
+               DRM_ERROR("Failed to validate FB for command submission\n");
+               return ret;
+       }
+
+       reserved_size = update->calc_fifo_size(update, num_hits);
+       cmd_start = vmw_fifo_reserve(update->dev_priv, reserved_size);
+       if (!cmd_start) {
+               DRM_ERROR("Failed to allocate FIFO space for plane update\n");
+               update->revert(update);
+               return -ENOMEM;
+       }
+       cmd_next = cmd_start;
+
+       if (update->post_prepare) {
+               curr_size = update->post_prepare(update, cmd_next);
+               cmd_next += curr_size;
+               submit_size += curr_size;
+       }
+
+       if (update->pre_clip) {
+               curr_size = update->pre_clip(update, cmd_next, num_hits);
+               cmd_next += curr_size;
+               submit_size += curr_size;
+       }
+
+       bb.x1 = INT_MAX;
+       bb.y1 = INT_MAX;
+       bb.x2 = INT_MIN;
+       bb.y2 = INT_MIN;
+
+       drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+       drm_atomic_for_each_plane_damage(&iter, &clip) {
+               uint32_t fb_x = clip.x1;
+               uint32_t fb_y = clip.y1;
+
+               vmw_du_translate_to_crtc(state, &clip);
+               if (update->clip) {
+                       curr_size = update->clip(update, cmd_next, &clip, fb_x,
+                                                fb_y);
+                       cmd_next += curr_size;
+                       submit_size += curr_size;
+               }
+               bb.x1 = min_t(int, bb.x1, clip.x1);
+               bb.y1 = min_t(int, bb.y1, clip.y1);
+               bb.x2 = max_t(int, bb.x2, clip.x2);
+               bb.y2 = max_t(int, bb.y2, clip.y2);
+       }
+
+       curr_size = update->post_clip(update, cmd_next, &bb);
+       submit_size += curr_size;
+
+       if (reserved_size < submit_size)
+               submit_size = 0;
+
+       vmw_fifo_commit(update->dev_priv, submit_size);
+
+       update->finish(update);
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h 
b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 31311298ec0b..26cad7e73afa 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -33,7 +33,115 @@
 #include <drm/drm_encoder.h>
 #include "vmwgfx_drv.h"
 
+/**
+ * struct vmw_du_update_plane - Closure structure for 
vmw_du_helper_plane_update
+ * @plane: Plane which is being updated.
+ * @old_state: Old state of plane.
+ * @dev_priv: Device private.
+ * @du: Display unit on which to update the plane.
+ * @vfb: Framebuffer which is blitted to display unit.
+ * @out_fence: Out fence for resource finish. (optional)
+ *
+ * This structure loosely represent the set of operations needed to perform a
+ * plane update on a display unit. Implementer will define that functionality
+ * according to the function callbacks for this structure. In brief it involves
+ * surface/buffer object validation, populate FIFO commands and command
+ * submission to the device.
+ */
+struct vmw_du_update_plane {
+       /**
+        * @prepare: Resource preparation and validation.
+        *
+        * This callback should be called to prepare the surface resource or the
+        * buffer object to validate it before command submission.
+        *
+        * RETURNS: 0 on success or a negative error code on failure.
+        */
+       int (*prepare)(struct vmw_du_update_plane *update);
 
+       /**
+        * @calc_fifo_size: Calculate fifo size.
+        *
+        * Determine fifo size for the commands needed for update. The number of
+        * damage clips on display unit @num_hits will be passed to allocate
+        * sufficient fifo space.
+        *
+        * RETURNS: Fifo size needed
+        */
+       uint32_t (*calc_fifo_size)(struct vmw_du_update_plane *update,
+                                  uint32_t num_hits);
+
+       /**
+        * @post_prepare: Populate fifo for resource preparation.
+        *
+        * Some surface resource or buffer object need some extra cmd submission
+        * like update GB image for proxy surface and define a GMRFB for screen
+        * object. That should should be done here as this callback will be
+        * called after FIFO allocation with the address of command buufer.
+        *
+        * This callback is optional.
+        *
+        * RETURNS: Size of commands populated to command buffer.
+        */
+       uint32_t (*post_prepare)(struct vmw_du_update_plane *update, void *cmd);
+
+       /**
+        * @pre_clip: Populate fifo before clip.
+        *
+        * This is where pre clip related command should be populated like
+        * surface copy/DMA, etc.
+        *
+        * This callback is optional.
+        *
+        * RETURNS: Size of commands populated to command buffer.
+        */
+       uint32_t (*pre_clip)(struct vmw_du_update_plane *update, void *cmd,
+                            uint32_t num_hits);
+
+       /**
+        * @clip: Populate fifo for clip.
+        *
+        * This is where to populate clips for surface copy/dma or blit commands
+        * if needed. This will be called times have damage in display unit,
+        * which is one if doing full update. @clip is the damage in destination
+        * coordinates which is crtc/DU and @src_x, @src_y is damage clip src in
+        * framebuffer coordinate.
+        *
+        * This callback is optional.
+        *
+        * RETURNS: Size of commands populated to command buffer.
+        */
+       uint32_t (*clip)(struct vmw_du_update_plane *update, void *cmd,
+                        struct drm_rect *clip, uint32_t src_x, uint32_t src_y);
+
+       /**
+        * @post_clip: Populate fifo after clip.
+        *
+        * This is where to populate display unit update commands or blit
+        * commands.
+        *
+        * RETURNS: Size of commands populated to command buffer.
+        */
+       uint32_t (*post_clip)(struct vmw_du_update_plane *update, void *cmd,
+                                   struct drm_rect *bb);
+
+       /**
+        * @finish: Finish surface resource or buffer object.
+        */
+       void (*finish)(struct vmw_du_update_plane *update);
+
+       /**
+        * @revert: Revert surface resource or buffer object in case of failure.
+        */
+       void (*revert)(struct vmw_du_update_plane *update);
+
+       struct drm_plane *plane;
+       struct drm_plane_state *old_state;
+       struct vmw_private *dev_priv;
+       struct vmw_display_unit *du;
+       struct vmw_framebuffer *vfb;
+       struct vmw_fence_obj **out_fence;
+};
 
 /**
  * struct vmw_kms_dirty - closure structure for the vmw_kms_helper_dirty
@@ -470,4 +578,21 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
 
 int vmw_kms_set_config(struct drm_mode_set *set,
                       struct drm_modeset_acquire_ctx *ctx);
+
+int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
+
+/**
+ * vmw_du_translate_to_crtc - Translate a rect from framebuffer to crtc
+ * @state: Plane state.
+ * @r: Rectangle to translate.
+ */
+static inline void vmw_du_translate_to_crtc(struct drm_plane_state *state,
+                                           struct drm_rect *r)
+{
+       int translate_crtc_x = -((state->src_x >> 16) - state->crtc_x);
+       int translate_crtc_y = -((state->src_y >> 16) - state->crtc_y);
+
+       drm_rect_translate(r, translate_crtc_x, translate_crtc_y);
+}
+
 #endif
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to