Commit 682565a6 authored by Uday Kiran Pichika's avatar Uday Kiran Pichika

WIP: modesetting: porting vrr support from amdgpu

Feature to support VRR in xserver modesetting DDX driver.
Verification is under progress.Checking is needed whether
the application is flipping when in the fullscreen mode
parent 2fe13a1f
Pipeline #136014 passed with stages
in 7 minutes and 14 seconds
......@@ -80,6 +80,12 @@ static Bool ms_pci_probe(DriverPtr driver,
intptr_t match_data);
static Bool ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data);
static Atom vrr_atom;
static Bool property_vectors_wrapped;
static Bool restore_property_vector;
static int (*saved_change_property) (ClientPtr client);
static int (*saved_delete_property) (ClientPtr client);
#ifdef XSERVER_LIBPCIACCESS
static const struct pci_id_match ms_device_match[] = {
{
......@@ -131,6 +137,7 @@ static const OptionInfoRec Options[] = {
{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
{OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_ATOMIC, "Atomic", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
......@@ -706,6 +713,130 @@ 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
ms_vrr_property_update(WindowPtr window, Bool variable_refresh)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen);
modesettingPtr ms = modesettingPTR(scrn);
struct ms_vrr_priv *priv = dixLookupPrivate(&window->devPrivates, &ms->drmmode.vrrPrivateKeyRec);
priv->variable_refresh = variable_refresh;
if (ms->flip_window == window && ms->drmmode.present_flipping)
ms_present_set_screen_vrr(scrn, variable_refresh);
}
static int
ms_change_property(ClientPtr client)
{
WindowPtr window = NULL;
int ret = 0;
REQUEST(xChangePropertyReq);
client->requestVector[X_ChangeProperty] = saved_change_property;
ret = saved_change_property(client);
if (restore_property_vector)
return ret;
client->requestVector[X_ChangeProperty] = ms_change_property;
if (ret != Success)
return ret;
ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
if (ret != Success)
return ret;
if (stuff->property == vrr_atom &&
xf86ScreenToScrn(window->drawable.pScreen)->PreInit ==
PreInit && stuff->format == 32 && stuff->nUnits == 1) {
uint32_t *value = (uint32_t *)(stuff + 1);
ms_vrr_property_update(window, *value != 0);
}
return ret;
}
/* Wrapper for xserver/dix/property.c:ProcDeleteProperty */
static int
ms_delete_property(ClientPtr client)
{
WindowPtr window;
int ret;
REQUEST(xDeletePropertyReq);
client->requestVector[X_DeleteProperty] = saved_delete_property;
ret = saved_delete_property(client);
if (restore_property_vector)
return ret;
client->requestVector[X_DeleteProperty] = ms_delete_property;
if (ret != Success)
return ret;
ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
if (ret != Success)
return ret;
if (stuff->property == vrr_atom &&
xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit)
ms_vrr_property_update(window, FALSE);
return ret;
}
static void
ms_unwrap_property_requests(ScrnInfoPtr scrn)
{
int i;
if (!property_vectors_wrapped)
return;
if (ProcVector[X_ChangeProperty] == ms_change_property)
ProcVector[X_ChangeProperty] = saved_change_property;
else
restore_property_vector = TRUE;
if (ProcVector[X_DeleteProperty] == ms_delete_property)
ProcVector[X_DeleteProperty] = saved_delete_property;
else
restore_property_vector = TRUE;
for (i = 0; i < currentMaxClients; i++) {
if (clients[i]->requestVector[X_ChangeProperty] == ms_change_property) {
clients[i]->requestVector[X_ChangeProperty] = saved_change_property;
} else {
restore_property_vector = TRUE;
}
if (clients[i]->requestVector[X_DeleteProperty] == ms_delete_property) {
clients[i]->requestVector[X_DeleteProperty] = saved_delete_property;
} else {
restore_property_vector = TRUE;
}
}
if (restore_property_vector) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Couldn't unwrap some window property request vectors\n");
}
property_vectors_wrapped = FALSE;
}
static void
FreeRec(ScrnInfoPtr pScrn)
{
......@@ -725,6 +856,7 @@ FreeRec(ScrnInfoPtr pScrn)
ms_ent = ms_ent_priv(pScrn);
ms_ent->fd_ref--;
if (!ms_ent->fd_ref) {
ms_unwrap_property_requests(pScrn);
if (ms->pEnt->location.type == BUS_PCI)
ret = drmClose(ms->fd);
else
......@@ -1053,6 +1185,13 @@ PreInit(ScrnInfoPtr pScrn, int flags)
ms->drmmode.shadow_enable ? "YES" : "NO");
ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms);
} else {
if (!pScrn->is_gpu) {
MessageType from = xf86GetOptValBool(ms->drmmode.Options, OPTION_VARIABLE_REFRESH,
&ms->vrr_support) ? X_CONFIG : X_DEFAULT;
xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n",
ms->vrr_support ? "en" : "dis");
}
}
ms->drmmode.pageflip =
......@@ -1451,6 +1590,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;
}
......@@ -1805,6 +1950,18 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
pScrn->vtSema = TRUE;
if (ms->vrr_support) {
if (!property_vectors_wrapped) {
saved_change_property = ProcVector[X_ChangeProperty];
ProcVector[X_ChangeProperty] = ms_change_property;
saved_delete_property = ProcVector[X_DeleteProperty];
ProcVector[X_DeleteProperty] = ms_delete_property;
property_vectors_wrapped = TRUE;
}
vrr_atom = MakeAtom("_VARIABLE_REFRESH",
strlen("_VARIABLE_REFRESH"), TRUE);
}
return TRUE;
}
......
......@@ -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,
......@@ -52,6 +56,7 @@ typedef enum {
OPTION_ZAPHOD_HEADS,
OPTION_DOUBLE_SHADOW,
OPTION_ATOMIC,
OPTION_VARIABLE_REFRESH,
} modesettingOpts;
typedef struct
......@@ -122,6 +127,10 @@ typedef struct _modesettingRec {
Bool kms_has_modifiers;
// vrr stuff
Bool vrr_support;
WindowPtr flip_window;
/* shadow API */
struct {
Bool (*Setup)(ScreenPtr);
......@@ -224,3 +233,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);
......@@ -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)
{
......@@ -2232,6 +2279,8 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num);
xorg_list_init(&drmmode_crtc->mode_list);
// NOTE(pichika) This block is currently unreachable, due to broken atomic
// userspace.
if (ms->atomic_modeset) {
props = drmModeObjectGetProperties(drmmode->fd, mode_res->crtcs[num],
DRM_MODE_OBJECT_CRTC);
......@@ -2250,6 +2299,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,
......@@ -3968,6 +4019,24 @@ 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;
//TODO(pichika) check if ms->fd == drmmode->fd
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 disabe page-flipping.
......
......@@ -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
......@@ -70,6 +70,22 @@ ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
return ms_get_crtc_ust_msc(xf86_crtc, ust, 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
*/
......@@ -282,6 +298,12 @@ ms_present_check_unflip(RRCrtcPtr crtc,
* return FALSE;
*/
// NOTE(strassek) amdgpu only sets this for check_flip, probably doesn't
// matter but make sure we're in that path we can probably just use
// screen->root instead
if (ms->drmmode.sprites_visible > 0)
ms->flip_window = window;
return TRUE;
}
......@@ -334,6 +356,15 @@ 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_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 +387,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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment