drm/vmwgfx: Add a new interface for plane update on a display unit
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. v3: Rebase to new resource validation. Signed-off-by: Deepak Rawat <drawat@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
This commit is contained in:
parent
b9fc5e01d1
commit
e41774c08e
|
@ -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)
|
||||
|
@ -2935,3 +2936,124 @@ 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.
|
||||
*
|
||||
* Return: 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;
|
||||
DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
|
||||
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;
|
||||
|
||||
if (update->vfb->bo) {
|
||||
struct vmw_framebuffer_bo *vfbbo =
|
||||
container_of(update->vfb, typeof(*vfbbo), base);
|
||||
|
||||
ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer, false,
|
||||
update->cpu_blit);
|
||||
} else {
|
||||
struct vmw_framebuffer_surface *vfbs =
|
||||
container_of(update->vfb, typeof(*vfbs), base);
|
||||
|
||||
ret = vmw_validation_add_resource(&val_ctx, &vfbs->surface->res,
|
||||
0, NULL, NULL);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vmw_validation_prepare(&val_ctx, update->mutex, update->intr);
|
||||
if (ret)
|
||||
goto out_unref;
|
||||
|
||||
reserved_size = update->calc_fifo_size(update, num_hits);
|
||||
cmd_start = vmw_fifo_reserve(update->dev_priv, reserved_size);
|
||||
if (!cmd_start) {
|
||||
ret = -ENOMEM;
|
||||
goto out_revert;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
vmw_kms_helper_validation_finish(update->dev_priv, NULL, &val_ctx,
|
||||
update->out_fence, NULL);
|
||||
return ret;
|
||||
|
||||
out_revert:
|
||||
vmw_validation_revert(&val_ctx);
|
||||
|
||||
out_unref:
|
||||
vmw_validation_unref_lists(&val_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,101 @@
|
|||
#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.
|
||||
* @mutex: The mutex used to protect resource reservation.
|
||||
* @cpu_blit: True if need cpu blit.
|
||||
* @intr: Whether to perform waits interruptible if possible.
|
||||
*
|
||||
* 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 {
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* Return: 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.
|
||||
*
|
||||
* Return: 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.
|
||||
*
|
||||
* Return: 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.
|
||||
*
|
||||
* Return: 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.
|
||||
*
|
||||
* Return: Size of commands populated to command buffer.
|
||||
*/
|
||||
uint32_t (*post_clip)(struct vmw_du_update_plane *update, void *cmd,
|
||||
struct drm_rect *bb);
|
||||
|
||||
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 mutex *mutex;
|
||||
bool cpu_blit;
|
||||
bool intr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct vmw_kms_dirty - closure structure for the vmw_kms_helper_dirty
|
||||
|
@ -458,4 +552,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
|
||||
|
|
Loading…
Reference in a new issue