summaryrefslogtreecommitdiff
path: root/hw/xfree86/drivers/modesetting
diff options
context:
space:
mode:
authorUday Kiran Pichika <pichika.uday.kiran@intel.com>2020-06-18 11:31:31 +0530
committerMartin Peres <martin.peres@free.fr>2020-09-08 08:00:20 +0000
commit9823ea4ed24db76b1e61d69a8da8f7599857d02a (patch)
treed9840c4828a49f73b77c40325e10c495b3b2bd01 /hw/xfree86/drivers/modesetting
parent42878790708c2a9ecdbb81f635e5e3a34842e34c (diff)
modesetting: Lay the foundation for enabling VRR
These changes have been ported from AMD GPU DDX driver. This patch adds support for setting the CRTC variable refresh property for suitable windows flipping via the Present extension. In order for a window to be suitable for variable refresh it must have the _VARIABLE_REFRESH property set by the MESA and inform Modesetting DDX driver with window property updates. Then the window must pass the checks required to be suitable for Present extension flips - it must cover the entire X screen and no other window may already be flipping. And also DRM connector should be VRR capable. With these conditions met every CRTC for the X screen will have their variable refresh property set to true. Kernel Changes to support this feature in I915 driver is under development. Tested with DOTA2, Xonotic and custom GLX apps. Signed-off-by: Uday Kiran Pichika <pichika.uday.kiran@intel.com>
Diffstat (limited to 'hw/xfree86/drivers/modesetting')
-rw-r--r--hw/xfree86/drivers/modesetting/driver.c12
-rw-r--r--hw/xfree86/drivers/modesetting/driver.h13
-rw-r--r--hw/xfree86/drivers/modesetting/drmmode_display.c103
-rw-r--r--hw/xfree86/drivers/modesetting/drmmode_display.h6
-rw-r--r--hw/xfree86/drivers/modesetting/present.c38
5 files changed, 170 insertions, 2 deletions
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 37bc51657..513816c70 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -706,6 +706,12 @@ msBlockHandler_oneshot(ScreenPtr pScreen, void *pTimeout)
drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE);
}
+Bool
+ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win) {
+ struct ms_vrr_priv *priv = dixLookupPrivate(&win->devPrivates, &ms->drmmode.vrrPrivateKeyRec);
+
+ return priv->variable_refresh;
+}
static void
FreeRec(ScrnInfoPtr pScrn)
{
@@ -1451,6 +1457,12 @@ CreateScreenResources(ScreenPtr pScreen)
pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
}
+ if (ms->vrr_support &&
+ !dixRegisterPrivateKey(&ms->drmmode.vrrPrivateKeyRec,
+ PRIVATE_WINDOW,
+ sizeof(struct ms_vrr_priv)))
+ return FALSE;
+
return ret;
}
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 7ee9f6827..7391bc4ab 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -43,6 +43,10 @@
#include "drmmode_display.h"
#define MS_LOGLEVEL_DEBUG 4
+struct ms_vrr_priv {
+ Bool variable_refresh;
+};
+
typedef enum {
OPTION_SW_CURSOR,
OPTION_DEVICE_PATH,
@@ -122,6 +126,13 @@ typedef struct _modesettingRec {
Bool kms_has_modifiers;
+ /* VRR support */
+ Bool vrr_support;
+ WindowPtr flip_window;
+
+ Bool is_connector_vrr_capable;
+ uint32_t connector_prop_id;
+
/* shadow API */
struct {
Bool (*Setup)(ScreenPtr);
@@ -224,3 +235,5 @@ Bool ms_do_pageflip(ScreenPtr screen,
#endif
int ms_flush_drm_events(ScreenPtr screen);
+Bool ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win);
+void ms_present_set_screen_vrr(ScrnInfoPtr scrn, Bool vrr_enabled);
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 9dd4b298f..5dbfa4149 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -2208,6 +2208,53 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
drmModeFreePlaneResources(kplane_res);
}
+static uint32_t
+drmmode_crtc_get_prop_id(uint32_t drm_fd,
+ drmModeObjectPropertiesPtr props,
+ char const* name)
+{
+ uint32_t i, prop_id = 0;
+
+ for (i = 0; !prop_id && i < props->count_props; ++i) {
+ drmModePropertyPtr drm_prop =
+ drmModeGetProperty(drm_fd, props->props[i]);
+
+ if (!drm_prop)
+ continue;
+
+ if (strcmp(drm_prop->name, name) == 0)
+ prop_id = drm_prop->prop_id;
+
+ drmModeFreeProperty(drm_prop);
+ }
+
+ return prop_id;
+}
+
+static void
+drmmode_crtc_vrr_init(int drm_fd, xf86CrtcPtr crtc)
+{
+ drmModeObjectPropertiesPtr drm_props;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ if (drmmode->vrr_prop_id)
+ return;
+
+ drm_props = drmModeObjectGetProperties(drm_fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC);
+
+ if (!drm_props)
+ return;
+
+ drmmode->vrr_prop_id = drmmode_crtc_get_prop_id(drm_fd,
+ drm_props,
+ "VRR_ENABLED");
+
+ drmModeFreeObjectProperties(drm_props);
+}
+
static unsigned int
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
{
@@ -2250,6 +2297,8 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
/* Hide any cursors which may be active from previous users */
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0);
+ drmmode_crtc_vrr_init(drmmode->fd, crtc);
+
/* Mark num'th crtc as in use on this device. */
ms_ent->assigned_crtcs |= (1 << num);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
@@ -2918,6 +2967,40 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id);
}
+static Bool
+drmmode_connector_check_vrr_capable(uint32_t drm_fd, int connector_id)
+{
+ uint32_t i;
+ Bool found = FALSE;
+ uint64_t prop_value = 0;
+ drmModeObjectPropertiesPtr props;
+ const char* prop_name = "VRR_CAPABLE";
+
+ props = drmModeObjectGetProperties(drm_fd, connector_id,
+ DRM_MODE_OBJECT_CONNECTOR);
+
+ for (i = 0; !found && i < props->count_props; ++i) {
+ drmModePropertyPtr drm_prop = drmModeGetProperty(drm_fd, props->props[i]);
+
+ if (!drm_prop)
+ continue;
+
+ if (strcasecmp(drm_prop->name, prop_name) == 0) {
+ prop_value = props->prop_values[i];
+ found = TRUE;
+ }
+
+ drmModeFreeProperty(drm_prop);
+ }
+
+ drmModeFreeObjectProperties(props);
+
+ if(found)
+ return prop_value ? TRUE : FALSE;
+
+ return FALSE;
+}
+
static unsigned int
drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic, int crtcshift)
{
@@ -3049,6 +3132,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
}
}
+ ms->is_connector_vrr_capable =
+ drmmode_connector_check_vrr_capable(drmmode->fd,
+ drmmode_output->output_id);
return 1;
out_free_encoders:
@@ -3968,6 +4054,23 @@ drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int *depth,
return;
}
+void
+drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ modesettingPtr ms = modesettingPTR(pScrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ if (drmmode->vrr_prop_id && drmmode_crtc->vrr_enabled != enabled &&
+ drmModeObjectSetProperty(ms->fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC,
+ drmmode->vrr_prop_id,
+ enabled) == 0)
+ drmmode_crtc->vrr_enabled = enabled;
+}
+
/*
* We hook the screen's cursor-sprite (swcursor) functions to see if a swcursor
* is active. When a swcursor is active we disable page-flipping.
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 2fb049bca..6360dd048 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -112,6 +112,7 @@ typedef struct {
DevPrivateKeyRec pixmapPrivateKeyRec;
DevScreenPrivateKeyRec spritePrivateKeyRec;
+ DevPrivateKeyRec vrrPrivateKeyRec;
/* Number of SW cursors currently visible on this screen */
int sprites_visible;
@@ -127,6 +128,8 @@ typedef struct {
Bool dri2_enable;
Bool present_enable;
+
+ uint32_t vrr_prop_id;
} drmmode_rec, *drmmode_ptr;
typedef struct {
@@ -193,6 +196,8 @@ typedef struct {
Bool enable_flipping;
Bool flipping_active;
+
+ Bool vrr_enabled;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
@@ -293,5 +298,6 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
int drmmode_crtc_flip(xf86CrtcPtr crtc, uint32_t fb_id, uint32_t flags, void *data);
void drmmode_set_dpms(ScrnInfoPtr scrn, int PowerManagementMode, int flags);
+void drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled);
#endif
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index fea2d663e..6e5b58938 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -71,6 +71,22 @@ ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
}
/*
+ * Changes the variable refresh state for every CRTC on the screen.
+ */
+void
+ms_present_set_screen_vrr(ScrnInfoPtr scrn, Bool vrr_enabled)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CrtcPtr crtc;
+ int i;
+
+ for (i = 0; i < config->num_crtc; i++) {
+ crtc = config->crtc[i];
+ drmmode_crtc_set_vrr(crtc, vrr_enabled);
+ }
+}
+
+/*
* Called when the queued vblank event has occurred
*/
static void
@@ -299,7 +315,12 @@ ms_present_check_flip(RRCrtcPtr crtc,
if (ms->drmmode.sprites_visible > 0)
return FALSE;
- return ms_present_check_unflip(crtc, window, pixmap, sync_flip, reason);
+ if(!ms_present_check_unflip(crtc, window, pixmap, sync_flip, reason))
+ return FALSE;
+
+ ms->flip_window = window;
+
+ return TRUE;
}
/*
@@ -321,7 +342,7 @@ ms_present_flip(RRCrtcPtr crtc,
Bool ret;
struct ms_present_vblank_event *event;
- if (!ms_present_check_flip(crtc, screen->root, pixmap, sync_flip, NULL))
+ if (!ms_present_check_flip(crtc, ms->flip_window, pixmap, sync_flip, NULL))
return FALSE;
event = calloc(1, sizeof(struct ms_present_vblank_event));
@@ -334,6 +355,17 @@ ms_present_flip(RRCrtcPtr crtc,
event->event_id = event_id;
event->unflip = FALSE;
+ /* A window can only flip if it covers the entire X screen.
+ * Only one window can flip at a time.
+ *
+ * If the window also has the variable refresh property then
+ * variable refresh supported can be enabled on every CRTC.
+ */
+ if (ms->vrr_support && ms->is_connector_vrr_capable &&
+ ms_window_has_variable_refresh(ms, ms->flip_window)) {
+ ms_present_set_screen_vrr(scrn, TRUE);
+ }
+
ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip,
ms_present_flip_handler, ms_present_flip_abort,
"Present-flip");
@@ -356,6 +388,8 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id)
int i;
struct ms_present_vblank_event *event;
+ ms_present_set_screen_vrr(scrn, FALSE);
+
event = calloc(1, sizeof(struct ms_present_vblank_event));
if (!event)
return;