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). Signed-off-by: Deepak Rawat <drawat@xxxxxxxxxx> --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 108 +++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 143 ++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 1edbae73d6d6..c1de8f609bf4 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) @@ -3077,3 +3078,110 @@ 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 display unit + * + * @update: The closure structure. + * + * 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. + * Iterator init returns negative error code if no need to do plane + * update. + */ + ret = drm_atomic_helper_damage_iter_init(&iter, old_state, state); + if (ret) + return 0; + + while (drm_atomic_helper_damage_iter_next(&iter, &clip)) + num_hits++; + + /* + * If all clips are outside plane src no need to do plane update on + * display unit + */ + 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); + while (drm_atomic_helper_damage_iter_next(&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..6bda8d3fb52f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -33,7 +33,132 @@ #include <drm/drm_encoder.h> #include "vmwgfx_drv.h" +/** + * struct vmw_du_update_plane - closure structure for vmw_du_helper_plane_update + * + * 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. + * + * @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: (optional) out fence for resource finish. + */ +struct vmw_du_update_plane { + /** + * @prepare: + * + * 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: + * + * 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: + * + * 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: + * + * 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: + * + * 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: + * + * 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 +595,22 @@ 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: rect 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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel