drm/vmwgfx: Break out implicit fb code
Preparation for supporting explicit fbs for screen objects and screen targets. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
This commit is contained in:
parent
b1097aeb6f
commit
75c0685549
|
@ -407,8 +407,9 @@ struct vmw_private {
|
|||
void *fb_info;
|
||||
enum vmw_display_unit_type active_display_unit;
|
||||
struct vmw_legacy_display *ldu_priv;
|
||||
struct vmw_screen_object_display *sou_priv;
|
||||
struct vmw_overlay *overlay_priv;
|
||||
unsigned num_implicit;
|
||||
struct vmw_framebuffer *implicit_fb;
|
||||
|
||||
/*
|
||||
* Context and surface management.
|
||||
|
|
|
@ -2095,3 +2095,95 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* vmw_kms_del_active - unregister a crtc binding to the implicit framebuffer
|
||||
*
|
||||
* @dev_priv: Pointer to a device private struct.
|
||||
* @du: The display unit of the crtc.
|
||||
*/
|
||||
void vmw_kms_del_active(struct vmw_private *dev_priv,
|
||||
struct vmw_display_unit *du)
|
||||
{
|
||||
lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
|
||||
|
||||
if (du->active_implicit) {
|
||||
if (--(dev_priv->num_implicit) == 0)
|
||||
dev_priv->implicit_fb = NULL;
|
||||
du->active_implicit = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vmw_kms_add_active - register a crtc binding to an implicit framebuffer
|
||||
*
|
||||
* @vmw_priv: Pointer to a device private struct.
|
||||
* @du: The display unit of the crtc.
|
||||
* @vfb: The implicit framebuffer
|
||||
*
|
||||
* Registers a binding to an implicit framebuffer.
|
||||
*/
|
||||
void vmw_kms_add_active(struct vmw_private *dev_priv,
|
||||
struct vmw_display_unit *du,
|
||||
struct vmw_framebuffer *vfb)
|
||||
{
|
||||
lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
|
||||
|
||||
WARN_ON_ONCE(!dev_priv->num_implicit && dev_priv->implicit_fb);
|
||||
|
||||
if (!du->active_implicit && du->is_implicit) {
|
||||
dev_priv->implicit_fb = vfb;
|
||||
du->active_implicit = true;
|
||||
dev_priv->num_implicit++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vmw_kms_screen_object_flippable - Check whether we can page-flip a crtc.
|
||||
*
|
||||
* @dev_priv: Pointer to device-private struct.
|
||||
* @crtc: The crtc we want to flip.
|
||||
*
|
||||
* Returns true or false depending whether it's OK to flip this crtc
|
||||
* based on the criterion that we must not have more than one implicit
|
||||
* frame-buffer at any one time.
|
||||
*/
|
||||
bool vmw_kms_crtc_flippable(struct vmw_private *dev_priv,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
|
||||
|
||||
lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
|
||||
|
||||
if (!du->is_implicit)
|
||||
return true;
|
||||
|
||||
if (dev_priv->num_implicit != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* vmw_kms_update_implicit_fb - Update the implicit fb.
|
||||
*
|
||||
* @dev_priv: Pointer to device-private struct.
|
||||
* @crtc: The crtc the new implicit frame-buffer is bound to.
|
||||
*/
|
||||
void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
|
||||
struct vmw_framebuffer *vfb;
|
||||
|
||||
lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
|
||||
|
||||
if (!du->is_implicit)
|
||||
return;
|
||||
|
||||
vfb = vmw_framebuffer_to_vfb(crtc->primary->fb);
|
||||
WARN_ON_ONCE(dev_priv->num_implicit != 1 &&
|
||||
dev_priv->implicit_fb != vfb);
|
||||
|
||||
dev_priv->implicit_fb = vfb;
|
||||
}
|
||||
|
|
|
@ -178,6 +178,7 @@ struct vmw_display_unit {
|
|||
int gui_x;
|
||||
int gui_y;
|
||||
bool is_implicit;
|
||||
bool active_implicit;
|
||||
};
|
||||
|
||||
#define vmw_crtc_to_du(x) \
|
||||
|
@ -254,6 +255,17 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
|
|||
struct drm_crtc **p_crtc,
|
||||
struct drm_display_mode **p_mode);
|
||||
void vmw_guess_mode_timing(struct drm_display_mode *mode);
|
||||
void vmw_kms_del_active(struct vmw_private *dev_priv,
|
||||
struct vmw_display_unit *du);
|
||||
void vmw_kms_add_active(struct vmw_private *dev_priv,
|
||||
struct vmw_display_unit *du,
|
||||
struct vmw_framebuffer *vfb);
|
||||
bool vmw_kms_crtc_flippable(struct vmw_private *dev_priv,
|
||||
struct drm_crtc *crtc);
|
||||
void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
|
||||
struct drm_crtc *crtc);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Legacy display unit functions - vmwgfx_ldu.c
|
||||
|
|
|
@ -74,19 +74,6 @@ struct vmw_kms_sou_dirty_cmd {
|
|||
SVGA3dCmdBlitSurfaceToScreen body;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Other structs.
|
||||
*/
|
||||
|
||||
struct vmw_screen_object_display {
|
||||
unsigned num_implicit;
|
||||
|
||||
struct vmw_framebuffer *implicit_fb;
|
||||
SVGAFifoCmdDefineGMRFB cur;
|
||||
struct vmw_dma_buffer *pinned_gmrfb;
|
||||
};
|
||||
|
||||
/**
|
||||
* Display unit using screen objects.
|
||||
*/
|
||||
|
@ -97,7 +84,6 @@ struct vmw_screen_object_unit {
|
|||
struct vmw_dma_buffer *buffer; /**< Backing store buffer */
|
||||
|
||||
bool defined;
|
||||
bool active_implicit;
|
||||
};
|
||||
|
||||
static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
|
||||
|
@ -116,33 +102,6 @@ static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
|
|||
vmw_sou_destroy(vmw_crtc_to_sou(crtc));
|
||||
}
|
||||
|
||||
static void vmw_sou_del_active(struct vmw_private *vmw_priv,
|
||||
struct vmw_screen_object_unit *sou)
|
||||
{
|
||||
struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
|
||||
|
||||
if (sou->active_implicit) {
|
||||
if (--(ld->num_implicit) == 0)
|
||||
ld->implicit_fb = NULL;
|
||||
sou->active_implicit = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void vmw_sou_add_active(struct vmw_private *vmw_priv,
|
||||
struct vmw_screen_object_unit *sou,
|
||||
struct vmw_framebuffer *vfb)
|
||||
{
|
||||
struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
|
||||
|
||||
BUG_ON(!ld->num_implicit && ld->implicit_fb);
|
||||
|
||||
if (!sou->active_implicit && sou->base.is_implicit) {
|
||||
ld->implicit_fb = vfb;
|
||||
sou->active_implicit = true;
|
||||
ld->num_implicit++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the fifo command to create a screen.
|
||||
*/
|
||||
|
@ -323,13 +282,13 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* sou only supports one fb active at the time */
|
||||
/* Only one active implicit frame-buffer at a time. */
|
||||
if (sou->base.is_implicit &&
|
||||
dev_priv->sou_priv->implicit_fb && vfb &&
|
||||
!(dev_priv->sou_priv->num_implicit == 1 &&
|
||||
sou->active_implicit) &&
|
||||
dev_priv->sou_priv->implicit_fb != vfb) {
|
||||
DRM_ERROR("Multiple framebuffers not supported\n");
|
||||
dev_priv->implicit_fb && vfb &&
|
||||
!(dev_priv->num_implicit == 1 &&
|
||||
sou->base.active_implicit) &&
|
||||
dev_priv->implicit_fb != vfb) {
|
||||
DRM_ERROR("Multiple implicit framebuffers not supported.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -351,7 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
|
|||
crtc->y = 0;
|
||||
crtc->enabled = false;
|
||||
|
||||
vmw_sou_del_active(dev_priv, sou);
|
||||
vmw_kms_del_active(dev_priv, &sou->base);
|
||||
|
||||
vmw_sou_backing_free(dev_priv, sou);
|
||||
|
||||
|
@ -415,7 +374,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
|
|||
return ret;
|
||||
}
|
||||
|
||||
vmw_sou_add_active(dev_priv, sou, vfb);
|
||||
vmw_kms_add_active(dev_priv, &sou->base, vfb);
|
||||
|
||||
connector->encoder = encoder;
|
||||
encoder->crtc = crtc;
|
||||
|
@ -428,39 +387,6 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this unit can be page flipped.
|
||||
* Must be called with the mode_config mutex held.
|
||||
*/
|
||||
static bool vmw_sou_screen_object_flippable(struct vmw_private *dev_priv,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
|
||||
|
||||
if (!sou->base.is_implicit)
|
||||
return true;
|
||||
|
||||
if (dev_priv->sou_priv->num_implicit != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the implicit fb to the current fb of this crtc.
|
||||
* Must be called with the mode_config mutex held.
|
||||
*/
|
||||
static void vmw_sou_update_implicit_fb(struct vmw_private *dev_priv,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct vmw_screen_object_unit *sou = vmw_crtc_to_sou(crtc);
|
||||
|
||||
BUG_ON(!sou->base.is_implicit);
|
||||
|
||||
dev_priv->sou_priv->implicit_fb =
|
||||
vmw_framebuffer_to_vfb(sou->base.crtc.primary->fb);
|
||||
}
|
||||
|
||||
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
|
@ -473,11 +399,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
|
|||
struct drm_vmw_rect vclips;
|
||||
int ret;
|
||||
|
||||
/* require ScreenObject support for page flipping */
|
||||
if (!dev_priv->sou_priv)
|
||||
return -ENOSYS;
|
||||
|
||||
if (!vmw_sou_screen_object_flippable(dev_priv, crtc))
|
||||
if (!vmw_kms_crtc_flippable(dev_priv, crtc))
|
||||
return -EINVAL;
|
||||
|
||||
crtc->primary->fb = fb;
|
||||
|
@ -522,7 +444,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
|
|||
vmw_fence_obj_unreference(&fence);
|
||||
|
||||
if (vmw_crtc_to_du(crtc)->is_implicit)
|
||||
vmw_sou_update_implicit_fb(dev_priv, crtc);
|
||||
vmw_kms_update_implicit_fb(dev_priv, crtc);
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -587,8 +509,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
|
|||
encoder = &sou->base.encoder;
|
||||
connector = &sou->base.connector;
|
||||
|
||||
sou->active_implicit = false;
|
||||
|
||||
sou->base.active_implicit = false;
|
||||
sou->base.pref_active = (unit == 0);
|
||||
sou->base.pref_width = dev_priv->initial_width;
|
||||
sou->base.pref_height = dev_priv->initial_height;
|
||||
|
@ -623,11 +544,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
int i, ret;
|
||||
|
||||
if (dev_priv->sou_priv) {
|
||||
DRM_INFO("sou system already on\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
|
||||
DRM_INFO("Not using screen objects,"
|
||||
" missing cap SCREEN_OBJECT_2\n");
|
||||
|
@ -635,16 +551,12 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
|
|||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL);
|
||||
if (unlikely(!dev_priv->sou_priv))
|
||||
goto err_no_mem;
|
||||
|
||||
dev_priv->sou_priv->num_implicit = 0;
|
||||
dev_priv->sou_priv->implicit_fb = NULL;
|
||||
dev_priv->num_implicit = 0;
|
||||
dev_priv->implicit_fb = NULL;
|
||||
|
||||
ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
|
||||
if (unlikely(ret != 0))
|
||||
goto err_free;
|
||||
return ret;
|
||||
|
||||
ret = drm_mode_create_dirty_info_property(dev);
|
||||
if (unlikely(ret != 0))
|
||||
|
@ -661,10 +573,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
|
|||
|
||||
err_vblank_cleanup:
|
||||
drm_vblank_cleanup(dev);
|
||||
err_free:
|
||||
kfree(dev_priv->sou_priv);
|
||||
dev_priv->sou_priv = NULL;
|
||||
err_no_mem:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -672,13 +580,8 @@ int vmw_kms_sou_close_display(struct vmw_private *dev_priv)
|
|||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
|
||||
if (!dev_priv->sou_priv)
|
||||
return -ENOSYS;
|
||||
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
kfree(dev_priv->sou_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue