2008-05-28 14:33:07 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
2011-09-29 13:34:17 +02:00
|
|
|
* Copyright 2011 Dave Airlie
|
2008-05-28 14:33:07 +02:00
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the
|
|
|
|
* next paragraph) shall be included in all copies or substantial portions
|
|
|
|
* of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
|
|
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
|
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
*
|
2011-09-29 13:34:17 +02:00
|
|
|
* Original Author: Alan Hourihane <alanh@tungstengraphics.com>
|
2014-10-31 00:45:12 +01:00
|
|
|
* Rewrite: Dave Airlie <airlied@redhat.com>
|
2008-05-28 14:33:07 +02:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-08-26 20:06:23 +02:00
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include "dix-config.h"
|
2008-05-28 14:33:07 +02:00
|
|
|
#endif
|
|
|
|
|
2011-09-29 15:13:58 +02:00
|
|
|
#include <unistd.h>
|
2011-09-29 13:28:59 +02:00
|
|
|
#include <fcntl.h>
|
2008-05-28 14:33:07 +02:00
|
|
|
#include "xf86.h"
|
2018-01-19 03:07:29 +01:00
|
|
|
#include "xf86Priv.h"
|
2008-05-28 14:33:07 +02:00
|
|
|
#include "xf86_OSproc.h"
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "xf86Pci.h"
|
|
|
|
#include "mipointer.h"
|
2019-06-24 21:46:26 +02:00
|
|
|
#include "mipointrst.h"
|
2008-05-28 14:33:07 +02:00
|
|
|
#include "micmap.h"
|
|
|
|
#include <X11/extensions/randr.h>
|
|
|
|
#include "fb.h"
|
|
|
|
#include "edid.h"
|
|
|
|
#include "xf86i2c.h"
|
|
|
|
#include "xf86Crtc.h"
|
|
|
|
#include "miscstruct.h"
|
|
|
|
#include "dixstruct.h"
|
|
|
|
#include "xf86xv.h"
|
|
|
|
#include <X11/extensions/Xv.h>
|
2014-08-26 20:06:23 +02:00
|
|
|
#include <xorg-config.h>
|
2012-06-05 15:43:21 +02:00
|
|
|
#ifdef XSERVER_PLATFORM_BUS
|
|
|
|
#include "xf86platformBus.h"
|
|
|
|
#endif
|
2017-04-26 01:03:00 +02:00
|
|
|
#ifdef XSERVER_LIBPCIACCESS
|
2008-05-28 14:33:07 +02:00
|
|
|
#include <pciaccess.h>
|
|
|
|
#endif
|
|
|
|
#include "driver.h"
|
|
|
|
|
2014-08-26 20:37:46 +02:00
|
|
|
static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y);
|
|
|
|
static Bool CloseScreen(ScreenPtr pScreen);
|
|
|
|
static Bool EnterVT(ScrnInfoPtr pScrn);
|
2008-05-28 14:33:07 +02:00
|
|
|
static void Identify(int flags);
|
|
|
|
static const OptionInfoRec *AvailableOptions(int chipid, int busid);
|
2014-10-08 09:39:15 +02:00
|
|
|
static ModeStatus ValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
|
|
|
|
Bool verbose, int flags);
|
2014-08-26 20:37:46 +02:00
|
|
|
static void FreeScreen(ScrnInfoPtr pScrn);
|
|
|
|
static void LeaveVT(ScrnInfoPtr pScrn);
|
|
|
|
static Bool SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode);
|
|
|
|
static Bool ScreenInit(ScreenPtr pScreen, int argc, char **argv);
|
2008-05-28 14:33:07 +02:00
|
|
|
static Bool PreInit(ScrnInfoPtr pScrn, int flags);
|
2008-05-28 16:55:36 +02:00
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
static Bool Probe(DriverPtr drv, int flags);
|
2011-09-29 13:28:59 +02:00
|
|
|
static Bool ms_pci_probe(DriverPtr driver,
|
2014-10-08 09:39:15 +02:00
|
|
|
int entity_num, struct pci_device *device,
|
|
|
|
intptr_t match_data);
|
|
|
|
static Bool ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data);
|
2011-09-29 13:28:59 +02:00
|
|
|
|
|
|
|
#ifdef XSERVER_LIBPCIACCESS
|
|
|
|
static const struct pci_id_match ms_device_match[] = {
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
|
|
|
|
0x00030000, 0x00ff0000, 0},
|
2011-09-29 13:28:59 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
{0, 0, 0},
|
2008-05-28 14:33:07 +02:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2015-11-11 13:32:05 +01:00
|
|
|
#ifndef XSERVER_PLATFORM_BUS
|
|
|
|
struct xf86_platform_device;
|
|
|
|
#endif
|
|
|
|
|
2012-06-05 15:43:21 +02:00
|
|
|
#ifdef XSERVER_PLATFORM_BUS
|
|
|
|
static Bool ms_platform_probe(DriverPtr driver,
|
2014-10-08 09:39:15 +02:00
|
|
|
int entity_num, int flags,
|
|
|
|
struct xf86_platform_device *device,
|
|
|
|
intptr_t match_data);
|
2012-06-05 15:43:21 +02:00
|
|
|
#endif
|
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
_X_EXPORT DriverRec modesetting = {
|
2008-05-28 16:55:36 +02:00
|
|
|
1,
|
|
|
|
"modesetting",
|
|
|
|
Identify,
|
|
|
|
Probe,
|
|
|
|
AvailableOptions,
|
|
|
|
NULL,
|
|
|
|
0,
|
2012-07-20 00:15:10 +02:00
|
|
|
ms_driver_func,
|
2011-09-29 13:28:59 +02:00
|
|
|
ms_device_match,
|
|
|
|
ms_pci_probe,
|
2012-06-05 15:43:21 +02:00
|
|
|
#ifdef XSERVER_PLATFORM_BUS
|
|
|
|
ms_platform_probe,
|
|
|
|
#endif
|
2008-05-28 14:33:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static SymTabRec Chipsets[] = {
|
2014-10-08 09:39:15 +02:00
|
|
|
{0, "kms"},
|
2008-05-28 16:55:36 +02:00
|
|
|
{-1, NULL}
|
2008-05-28 14:33:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const OptionInfoRec Options[] = {
|
2008-05-28 16:55:36 +02:00
|
|
|
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
|
2014-10-08 09:39:15 +02:00
|
|
|
{OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE},
|
|
|
|
{OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
|
2013-12-28 20:32:10 +01:00
|
|
|
{OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
|
modesetting: Implement page flipping support for Present.
Based on code by Keith Packard, Eric Anholt, and Jason Ekstrand.
v2:
- Fix double free and flip_count underrun (caught by Mario Kleiner).
- Don't leak flip_vblank_event on the error_out path (Mario).
- Use the updated ms_flush_drm_events API (Mario, Ken).
v3: Hack around DPMS shenanigans. If all monitors are DPMS off, then
there is no active framebuffer; attempting to pageflip will hit the
error_undo paths, causing us to drmModeRmFB with no framebuffer,
which confuses the kernel into doing full modesets and generally
breaks things. To avoid this, make ms_present_check_flip check that
some CRTCs are enabled and DPMS on. This is an ugly hack that would
get better with atomic modesetting, or some core Present work.
v4:
- Don't do pageflipping if CRTCs are rotated (caught by Jason Ekstrand).
- Make pageflipping optional (Option "PageFlip" in xorg.conf.d), but
enabled by default.
v5: Initialize num_crtcs_on to 0 (caught by Michel Dänzer).
[airlied: took over]
v6: merge async flip support from Mario Kleiner
free sequence after failed vblank queue
handle unflip while DPMS'ed off (Michel)
move flip tracking into its own structure, and
fix up reference counting issues, and add comments.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Acked-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
2015-01-27 06:29:23 +01:00
|
|
|
{OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
|
2015-07-22 04:56:13 +02:00
|
|
|
{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
|
2015-07-22 18:14:08 +02:00
|
|
|
{OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE},
|
2019-04-25 11:46:41 +02:00
|
|
|
{OPTION_ATOMIC, "Atomic", OPTV_BOOLEAN, {0}, FALSE},
|
2008-05-28 16:55:36 +02:00
|
|
|
{-1, NULL, OPTV_NONE, {0}, FALSE}
|
2008-05-28 14:33:07 +02:00
|
|
|
};
|
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
int ms_entity_index = -1;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
|
|
|
static MODULESETUPPROTO(Setup);
|
|
|
|
|
|
|
|
static XF86ModuleVersionInfo VersRec = {
|
2008-05-28 16:55:36 +02:00
|
|
|
"modesetting",
|
|
|
|
MODULEVENDORSTRING,
|
|
|
|
MODINFOSTRING1,
|
|
|
|
MODINFOSTRING2,
|
|
|
|
XORG_VERSION_CURRENT,
|
2014-08-26 20:06:23 +02:00
|
|
|
XORG_VERSION_MAJOR,
|
|
|
|
XORG_VERSION_MINOR,
|
|
|
|
XORG_VERSION_PATCH,
|
2008-05-28 16:55:36 +02:00
|
|
|
ABI_CLASS_VIDEODRV,
|
|
|
|
ABI_VIDEODRV_VERSION,
|
|
|
|
MOD_CLASS_VIDEODRV,
|
|
|
|
{0, 0, 0, 0}
|
2008-05-28 14:33:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
_X_EXPORT XF86ModuleData modesettingModuleData = { &VersRec, Setup, NULL };
|
|
|
|
|
2014-08-26 20:41:46 +02:00
|
|
|
static void *
|
2014-10-08 09:39:15 +02:00
|
|
|
Setup(void *module, void *opts, int *errmaj, int *errmin)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
static Bool setupDone = 0;
|
|
|
|
|
|
|
|
/* This module should be loaded only once, but check to be sure.
|
|
|
|
*/
|
|
|
|
if (!setupDone) {
|
2014-10-08 09:39:15 +02:00
|
|
|
setupDone = 1;
|
|
|
|
xf86AddDriver(&modesetting, module, HaveDriverFuncs);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The return value must be non-NULL on success even though there
|
|
|
|
* is no TearDownProc.
|
|
|
|
*/
|
|
|
|
return (void *) 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (errmaj)
|
|
|
|
*errmaj = LDR_ONCEONLY;
|
|
|
|
return NULL;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
Identify(int flags)
|
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers",
|
2014-10-08 09:39:15 +02:00
|
|
|
Chipsets);
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn)
|
|
|
|
{
|
|
|
|
DevUnion *pPriv;
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
|
|
|
pPriv = xf86GetEntityPrivate(ms->pEnt->index,
|
|
|
|
ms_entity_index);
|
|
|
|
return pPriv->ptr;
|
|
|
|
}
|
|
|
|
|
2018-01-19 03:07:29 +01:00
|
|
|
static int
|
|
|
|
get_passed_fd(void)
|
|
|
|
{
|
|
|
|
if (xf86DRMMasterFd >= 0) {
|
|
|
|
xf86DrvMsg(-1, X_INFO, "Using passed DRM master file descriptor %d\n", xf86DRMMasterFd);
|
|
|
|
return dup(xf86DRMMasterFd);
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static int
|
|
|
|
open_hw(const char *dev)
|
2011-09-29 13:28:59 +02:00
|
|
|
{
|
|
|
|
int fd;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2018-01-19 03:07:29 +01:00
|
|
|
if ((fd = get_passed_fd()) != -1)
|
|
|
|
return fd;
|
|
|
|
|
2011-09-29 13:28:59 +02:00
|
|
|
if (dev)
|
2018-05-18 11:23:01 +02:00
|
|
|
fd = open(dev, O_RDWR | O_CLOEXEC, 0);
|
2011-09-29 13:28:59 +02:00
|
|
|
else {
|
2014-10-08 09:39:15 +02:00
|
|
|
dev = getenv("KMSDEVICE");
|
2018-05-18 11:23:01 +02:00
|
|
|
if ((NULL == dev) || ((fd = open(dev, O_RDWR | O_CLOEXEC, 0)) == -1)) {
|
2014-10-08 09:39:15 +02:00
|
|
|
dev = "/dev/dri/card0";
|
2018-05-18 11:23:01 +02:00
|
|
|
fd = open(dev, O_RDWR | O_CLOEXEC, 0);
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
2011-09-29 13:28:59 +02:00
|
|
|
}
|
2012-03-03 14:09:24 +01:00
|
|
|
if (fd == -1)
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86DrvMsg(-1, X_ERROR, "open %s: %s\n", dev, strerror(errno));
|
2011-09-29 13:28:59 +02:00
|
|
|
|
2012-03-03 14:09:24 +01:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static int
|
2016-06-14 11:58:01 +02:00
|
|
|
check_outputs(int fd, int *count)
|
2013-06-12 14:05:19 +02:00
|
|
|
{
|
|
|
|
drmModeResPtr res = drmModeGetResources(fd);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!res)
|
|
|
|
return FALSE;
|
2016-06-14 11:58:01 +02:00
|
|
|
|
|
|
|
if (count)
|
|
|
|
*count = res->count_connectors;
|
|
|
|
|
2013-06-12 14:05:19 +02:00
|
|
|
ret = res->count_connectors > 0;
|
2018-03-07 19:45:31 +01:00
|
|
|
#if defined(GLAMOR_HAS_GBM_LINEAR)
|
2016-06-14 11:58:01 +02:00
|
|
|
if (ret == FALSE) {
|
|
|
|
uint64_t value = 0;
|
|
|
|
if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0 &&
|
|
|
|
(value & DRM_PRIME_CAP_EXPORT))
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
2013-06-12 14:05:19 +02:00
|
|
|
drmModeFreeResources(res);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static Bool
|
|
|
|
probe_hw(const char *dev, struct xf86_platform_device *platform_dev)
|
2012-03-03 14:09:24 +01:00
|
|
|
{
|
2014-03-18 15:48:22 +01:00
|
|
|
int fd;
|
|
|
|
|
2018-03-04 22:00:05 +01:00
|
|
|
#ifdef XF86_PDEV_SERVER_FD
|
2014-03-18 15:48:22 +01:00
|
|
|
if (platform_dev && (platform_dev->flags & XF86_PDEV_SERVER_FD)) {
|
2014-08-26 20:43:54 +02:00
|
|
|
fd = xf86_platform_device_odev_attributes(platform_dev)->fd;
|
2014-03-18 15:48:22 +01:00
|
|
|
if (fd == -1)
|
|
|
|
return FALSE;
|
2016-06-14 11:58:01 +02:00
|
|
|
return check_outputs(fd, NULL);
|
2014-03-18 15:48:22 +01:00
|
|
|
}
|
2018-03-04 22:00:05 +01:00
|
|
|
#endif
|
2014-03-18 15:48:22 +01:00
|
|
|
|
|
|
|
fd = open_hw(dev);
|
2012-03-03 14:09:24 +01:00
|
|
|
if (fd != -1) {
|
2016-06-14 11:58:01 +02:00
|
|
|
int ret = check_outputs(fd, NULL);
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2012-03-03 14:09:24 +01:00
|
|
|
close(fd);
|
2013-06-12 14:05:19 +02:00
|
|
|
return ret;
|
2012-03-03 14:09:24 +01:00
|
|
|
}
|
|
|
|
return FALSE;
|
2011-09-29 13:28:59 +02:00
|
|
|
}
|
|
|
|
|
2012-05-09 10:32:05 +02:00
|
|
|
static char *
|
|
|
|
ms_DRICreatePCIBusID(const struct pci_device *dev)
|
|
|
|
{
|
|
|
|
char *busID;
|
|
|
|
|
|
|
|
if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
|
|
|
|
dev->domain, dev->bus, dev->dev, dev->func) == -1)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return busID;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static Bool
|
|
|
|
probe_hw_pci(const char *dev, struct pci_device *pdev)
|
2012-05-09 10:32:05 +02:00
|
|
|
{
|
2013-06-12 14:05:19 +02:00
|
|
|
int ret = FALSE, fd = open_hw(dev);
|
2012-05-09 10:32:05 +02:00
|
|
|
char *id, *devid;
|
2012-06-22 16:26:28 +02:00
|
|
|
drmSetVersion sv;
|
2012-05-09 10:32:05 +02:00
|
|
|
|
|
|
|
if (fd == -1)
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2012-05-09 10:32:05 +02:00
|
|
|
|
2012-06-22 16:26:28 +02:00
|
|
|
sv.drm_di_major = 1;
|
|
|
|
sv.drm_di_minor = 4;
|
|
|
|
sv.drm_dd_major = -1;
|
|
|
|
sv.drm_dd_minor = -1;
|
|
|
|
if (drmSetInterfaceVersion(fd, &sv)) {
|
|
|
|
close(fd);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-05-09 10:32:05 +02:00
|
|
|
id = drmGetBusid(fd);
|
|
|
|
devid = ms_DRICreatePCIBusID(pdev);
|
|
|
|
|
2013-06-12 14:05:19 +02:00
|
|
|
if (id && devid && !strcmp(id, devid))
|
2016-06-14 11:58:01 +02:00
|
|
|
ret = check_outputs(fd, NULL);
|
2012-05-09 10:32:05 +02:00
|
|
|
|
2014-02-21 03:48:42 +01:00
|
|
|
close(fd);
|
2013-06-12 14:05:19 +02:00
|
|
|
free(id);
|
|
|
|
free(devid);
|
|
|
|
return ret;
|
2012-05-09 10:32:05 +02:00
|
|
|
}
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
static const OptionInfoRec *
|
|
|
|
AvailableOptions(int chipid, int busid)
|
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
return Options;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
2012-07-20 00:15:10 +02:00
|
|
|
static Bool
|
|
|
|
ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
|
|
|
|
{
|
|
|
|
xorgHWFlags *flag;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2012-07-20 00:15:10 +02:00
|
|
|
switch (op) {
|
2014-10-08 09:39:15 +02:00
|
|
|
case GET_REQUIRED_HW_INTERFACES:
|
|
|
|
flag = (CARD32 *) data;
|
|
|
|
(*flag) = 0;
|
|
|
|
return TRUE;
|
|
|
|
case SUPPORTS_SERVER_FDS:
|
|
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
2012-07-20 00:15:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-27 01:59:37 +02:00
|
|
|
static void
|
|
|
|
ms_setup_scrn_hooks(ScrnInfoPtr scrn)
|
|
|
|
{
|
|
|
|
scrn->driverVersion = 1;
|
|
|
|
scrn->driverName = "modesetting";
|
|
|
|
scrn->name = "modeset";
|
|
|
|
|
|
|
|
scrn->Probe = NULL;
|
|
|
|
scrn->PreInit = PreInit;
|
|
|
|
scrn->ScreenInit = ScreenInit;
|
|
|
|
scrn->SwitchMode = SwitchMode;
|
|
|
|
scrn->AdjustFrame = AdjustFrame;
|
|
|
|
scrn->EnterVT = EnterVT;
|
|
|
|
scrn->LeaveVT = LeaveVT;
|
|
|
|
scrn->FreeScreen = FreeScreen;
|
|
|
|
scrn->ValidMode = ValidMode;
|
|
|
|
}
|
|
|
|
|
2015-11-16 00:05:27 +01:00
|
|
|
static void
|
|
|
|
ms_setup_entity(ScrnInfoPtr scrn, int entity_num)
|
|
|
|
{
|
|
|
|
DevUnion *pPriv;
|
|
|
|
|
|
|
|
xf86SetEntitySharable(entity_num);
|
|
|
|
|
|
|
|
if (ms_entity_index == -1)
|
|
|
|
ms_entity_index = xf86AllocateEntityPrivateIndex();
|
|
|
|
|
|
|
|
pPriv = xf86GetEntityPrivate(entity_num,
|
|
|
|
ms_entity_index);
|
|
|
|
|
|
|
|
xf86SetEntityInstanceForScreen(scrn, entity_num, xf86GetNumEntityInstances(entity_num) - 1);
|
|
|
|
|
|
|
|
if (!pPriv->ptr)
|
|
|
|
pPriv->ptr = xnfcalloc(sizeof(modesettingEntRec), 1);
|
|
|
|
}
|
|
|
|
|
2017-04-26 01:03:00 +02:00
|
|
|
#ifdef XSERVER_LIBPCIACCESS
|
2008-05-28 14:33:07 +02:00
|
|
|
static Bool
|
2011-09-29 13:28:59 +02:00
|
|
|
ms_pci_probe(DriverPtr driver,
|
2014-10-08 09:39:15 +02:00
|
|
|
int entity_num, struct pci_device *dev, intptr_t match_data)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
ScrnInfoPtr scrn = NULL;
|
|
|
|
|
2011-09-29 13:28:59 +02:00
|
|
|
scrn = xf86ConfigPciEntity(scrn, 0, entity_num, NULL,
|
2014-10-08 09:39:15 +02:00
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
2011-09-29 13:28:59 +02:00
|
|
|
if (scrn) {
|
2014-10-08 09:39:15 +02:00
|
|
|
const char *devpath;
|
|
|
|
GDevPtr devSection = xf86GetDevFromEntity(scrn->entityList[0],
|
|
|
|
scrn->entityInstanceList[0]);
|
|
|
|
|
|
|
|
devpath = xf86FindOptionValue(devSection->options, "kmsdev");
|
|
|
|
if (probe_hw_pci(devpath, dev)) {
|
2014-08-27 01:59:37 +02:00
|
|
|
ms_setup_scrn_hooks(scrn);
|
2014-10-08 09:39:15 +02:00
|
|
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
|
|
|
|
"claimed PCI slot %d@%d:%d:%d\n",
|
|
|
|
dev->bus, dev->domain, dev->dev, dev->func);
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
"using %s\n", devpath ? devpath : "default device");
|
2015-11-16 00:05:27 +01:00
|
|
|
|
|
|
|
ms_setup_entity(scrn, entity_num);
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
scrn = NULL;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
|
|
|
return scrn != NULL;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
2011-09-29 13:28:59 +02:00
|
|
|
#endif
|
|
|
|
|
2012-06-05 15:43:21 +02:00
|
|
|
#ifdef XSERVER_PLATFORM_BUS
|
|
|
|
static Bool
|
|
|
|
ms_platform_probe(DriverPtr driver,
|
2014-10-08 09:39:15 +02:00
|
|
|
int entity_num, int flags, struct xf86_platform_device *dev,
|
|
|
|
intptr_t match_data)
|
2012-06-05 15:43:21 +02:00
|
|
|
{
|
|
|
|
ScrnInfoPtr scrn = NULL;
|
2014-08-26 20:43:54 +02:00
|
|
|
const char *path = xf86_platform_device_odev_attributes(dev)->path;
|
2012-06-05 15:43:21 +02:00
|
|
|
int scr_flags = 0;
|
|
|
|
|
|
|
|
if (flags & PLATFORM_PROBE_GPU_SCREEN)
|
2014-10-08 09:39:15 +02:00
|
|
|
scr_flags = XF86_ALLOCATE_GPU_SCREEN;
|
2012-06-05 15:43:21 +02:00
|
|
|
|
2014-03-18 15:48:22 +01:00
|
|
|
if (probe_hw(path, dev)) {
|
2012-06-05 15:43:21 +02:00
|
|
|
scrn = xf86AllocateScreen(driver, scr_flags);
|
2015-07-22 04:56:13 +02:00
|
|
|
if (xf86IsEntitySharable(entity_num))
|
|
|
|
xf86SetEntityShared(entity_num);
|
2012-06-05 15:43:21 +02:00
|
|
|
xf86AddEntityToScreen(scrn, entity_num);
|
|
|
|
|
2014-08-27 01:59:37 +02:00
|
|
|
ms_setup_scrn_hooks(scrn);
|
|
|
|
|
2012-06-05 15:43:21 +02:00
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
"using drv %s\n", path ? path : "default device");
|
2015-07-22 04:56:13 +02:00
|
|
|
|
2015-11-16 00:05:27 +01:00
|
|
|
ms_setup_entity(scrn, entity_num);
|
2012-06-05 15:43:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return scrn != NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
static Bool
|
|
|
|
Probe(DriverPtr drv, int flags)
|
|
|
|
{
|
2011-09-29 15:13:58 +02:00
|
|
|
int i, numDevSections;
|
2008-05-28 16:55:36 +02:00
|
|
|
GDevPtr *devSections;
|
|
|
|
Bool foundScreen = FALSE;
|
2013-11-15 05:26:36 +01:00
|
|
|
const char *dev;
|
2011-09-29 15:13:58 +02:00
|
|
|
ScrnInfoPtr scrn = NULL;
|
2011-09-29 13:28:59 +02:00
|
|
|
|
|
|
|
/* For now, just bail out for PROBE_DETECT. */
|
|
|
|
if (flags & PROBE_DETECT)
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the config file Device sections that match this
|
|
|
|
* driver, and return if there are none.
|
|
|
|
*/
|
|
|
|
if ((numDevSections = xf86MatchDevice("modesetting", &devSections)) <= 0) {
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
2011-09-29 13:28:59 +02:00
|
|
|
for (i = 0; i < numDevSections; i++) {
|
2015-11-16 00:05:27 +01:00
|
|
|
int entity_num;
|
2014-10-08 09:39:15 +02:00
|
|
|
dev = xf86FindOptionValue(devSections[i]->options, "kmsdev");
|
|
|
|
if (probe_hw(dev, NULL)) {
|
|
|
|
|
2015-11-16 00:05:27 +01:00
|
|
|
entity_num = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
|
|
|
|
scrn = xf86ConfigFbEntity(scrn, 0, entity_num, NULL, NULL, NULL, NULL);
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (scrn) {
|
|
|
|
foundScreen = TRUE;
|
2014-08-27 01:59:37 +02:00
|
|
|
ms_setup_scrn_hooks(scrn);
|
2014-10-08 09:39:15 +02:00
|
|
|
scrn->Probe = Probe;
|
|
|
|
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
"using %s\n", dev ? dev : "default device");
|
2015-11-16 00:05:27 +01:00
|
|
|
ms_setup_entity(scrn, entity_num);
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
free(devSections);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
return foundScreen;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
GetRec(ScrnInfoPtr pScrn)
|
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
if (pScrn->driverPrivate)
|
2014-10-08 09:39:15 +02:00
|
|
|
return TRUE;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
return TRUE;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static int
|
|
|
|
dispatch_dirty_region(ScrnInfoPtr scrn,
|
|
|
|
PixmapPtr pixmap, DamagePtr damage, int fb_id)
|
2011-09-29 13:38:26 +02:00
|
|
|
{
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
2012-07-19 06:12:59 +02:00
|
|
|
RegionPtr dirty = DamageRegion(damage);
|
2011-09-29 13:38:26 +02:00
|
|
|
unsigned num_cliprects = REGION_NUM_RECTS(dirty);
|
2014-12-20 04:34:34 +01:00
|
|
|
int ret = 0;
|
2011-09-29 13:38:26 +02:00
|
|
|
|
|
|
|
if (num_cliprects) {
|
2015-03-22 01:12:06 +01:00
|
|
|
drmModeClip *clip = xallocarray(num_cliprects, sizeof(drmModeClip));
|
2014-10-08 09:39:15 +02:00
|
|
|
BoxPtr rect = REGION_RECTS(dirty);
|
2014-12-20 04:34:34 +01:00
|
|
|
int i;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
|
|
|
if (!clip)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* XXX no need for copy? */
|
|
|
|
for (i = 0; i < num_cliprects; i++, rect++) {
|
|
|
|
clip[i].x1 = rect->x1;
|
|
|
|
clip[i].y1 = rect->y1;
|
|
|
|
clip[i].x2 = rect->x2;
|
|
|
|
clip[i].y2 = rect->y2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO query connector property to see if this is needed */
|
|
|
|
ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects);
|
2016-07-18 18:46:51 +02:00
|
|
|
|
|
|
|
/* if we're swamping it with work, try one at a time */
|
|
|
|
if (ret == -EINVAL) {
|
|
|
|
for (i = 0; i < num_cliprects; i++) {
|
|
|
|
if ((ret = drmModeDirtyFB(ms->fd, fb_id, &clip[i], 1)) < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
free(clip);
|
|
|
|
DamageEmpty(damage);
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
2014-12-20 04:34:34 +01:00
|
|
|
return ret;
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static void
|
|
|
|
dispatch_dirty(ScreenPtr pScreen)
|
2012-07-19 06:12:59 +02:00
|
|
|
{
|
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
|
|
|
PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen);
|
|
|
|
int fb_id = ms->drmmode.fb_id;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id);
|
|
|
|
if (ret == -EINVAL || ret == -ENOSYS) {
|
2014-10-08 09:39:15 +02:00
|
|
|
ms->dirty_enabled = FALSE;
|
|
|
|
DamageUnregister(ms->damage);
|
|
|
|
DamageDestroy(ms->damage);
|
|
|
|
ms->damage = NULL;
|
|
|
|
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
|
|
|
"Disabling kernel dirty updates, not required.\n");
|
|
|
|
return;
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static void
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
dispatch_dirty_pixmap(ScrnInfoPtr scrn, xf86CrtcPtr crtc, PixmapPtr ppix)
|
2012-07-19 06:12:59 +02:00
|
|
|
{
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
|
|
|
|
DamagePtr damage = ppriv->slave_damage;
|
2012-07-19 06:12:59 +02:00
|
|
|
int fb_id = ppriv->fb_id;
|
|
|
|
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
dispatch_dirty_region(scrn, ppix, damage, fb_id);
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static void
|
|
|
|
dispatch_slave_dirty(ScreenPtr pScreen)
|
2012-07-19 06:12:59 +02:00
|
|
|
{
|
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
|
|
|
int c;
|
|
|
|
|
|
|
|
for (c = 0; c < xf86_config->num_crtc; c++) {
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86CrtcPtr crtc = xf86_config->crtc[c];
|
2016-06-17 05:06:49 +02:00
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
2016-06-17 05:06:49 +02:00
|
|
|
if (!drmmode_crtc)
|
2014-10-08 09:39:15 +02:00
|
|
|
continue;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
if (drmmode_crtc->prime_pixmap)
|
|
|
|
dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap);
|
|
|
|
if (drmmode_crtc->prime_pixmap_back)
|
|
|
|
dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap_back);
|
2011-09-29 13:38:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-09 09:15:44 +02:00
|
|
|
static void
|
2016-09-15 14:35:52 +02:00
|
|
|
redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty, int *timeout)
|
2015-06-09 09:15:44 +02:00
|
|
|
{
|
2016-04-29 06:01:29 +02:00
|
|
|
RegionRec pixregion;
|
2015-06-09 09:15:44 +02:00
|
|
|
|
2016-04-29 06:01:29 +02:00
|
|
|
PixmapRegionInit(&pixregion, dirty->slave_dst);
|
|
|
|
DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
|
|
|
|
PixmapSyncDirtyHelper(dirty);
|
2015-06-09 09:15:44 +02:00
|
|
|
|
2016-09-15 14:28:35 +02:00
|
|
|
if (!screen->isGPU) {
|
2017-05-16 20:37:14 +02:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
2017-10-20 10:05:33 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
|
2016-09-15 14:28:35 +02:00
|
|
|
/*
|
|
|
|
* When copying from the master framebuffer to the shared pixmap,
|
|
|
|
* we must ensure the copy is complete before the slave starts a
|
|
|
|
* copy to its own framebuffer (some slaves scanout directly from
|
|
|
|
* the shared pixmap, but not all).
|
|
|
|
*/
|
|
|
|
if (ms->drmmode.glamor)
|
2019-11-18 22:46:44 +01:00
|
|
|
ms->glamor.finish(screen);
|
2016-10-15 06:13:43 +02:00
|
|
|
#endif
|
2016-09-15 14:35:52 +02:00
|
|
|
/* Ensure the slave processes the damage immediately */
|
|
|
|
if (timeout)
|
|
|
|
*timeout = 0;
|
2016-09-15 14:28:35 +02:00
|
|
|
}
|
|
|
|
|
2016-04-29 06:01:29 +02:00
|
|
|
DamageRegionProcessPending(&dirty->slave_dst->drawable);
|
|
|
|
RegionUninit(&pixregion);
|
2015-06-09 09:15:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-09-15 14:35:52 +02:00
|
|
|
ms_dirty_update(ScreenPtr screen, int *timeout)
|
2015-06-09 09:15:44 +02:00
|
|
|
{
|
2016-06-17 05:06:56 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
|
|
|
|
|
2016-04-29 06:01:29 +02:00
|
|
|
RegionPtr region;
|
|
|
|
PixmapDirtyUpdatePtr ent;
|
|
|
|
|
|
|
|
if (xorg_list_is_empty(&screen->pixmap_dirty_list))
|
|
|
|
return;
|
|
|
|
|
|
|
|
xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
|
|
|
|
region = DamageRegion(ent->damage);
|
|
|
|
if (RegionNotEmpty(region)) {
|
2018-08-27 07:37:38 +02:00
|
|
|
if (!screen->isGPU) {
|
|
|
|
msPixmapPrivPtr ppriv =
|
|
|
|
msGetPixmapPriv(&ms->drmmode, ent->slave_dst->master_pixmap);
|
2016-06-17 05:06:56 +02:00
|
|
|
|
2018-08-27 07:37:38 +02:00
|
|
|
if (ppriv->notify_on_damage) {
|
|
|
|
ppriv->notify_on_damage = FALSE;
|
2016-06-17 05:06:56 +02:00
|
|
|
|
2018-08-27 07:37:38 +02:00
|
|
|
ent->slave_dst->drawable.pScreen->
|
|
|
|
SharedPixmapNotifyDamage(ent->slave_dst);
|
|
|
|
}
|
2016-06-17 05:06:56 +02:00
|
|
|
|
2018-08-27 07:37:38 +02:00
|
|
|
/* Requested manual updating */
|
|
|
|
if (ppriv->defer_dirty_update)
|
|
|
|
continue;
|
|
|
|
}
|
2016-06-17 05:06:56 +02:00
|
|
|
|
2016-09-15 14:35:52 +02:00
|
|
|
redisplay_dirty(screen, ent, timeout);
|
2016-04-29 06:01:29 +02:00
|
|
|
DamageEmpty(ent->damage);
|
2015-06-09 09:15:44 +02:00
|
|
|
}
|
2016-04-29 06:01:29 +02:00
|
|
|
}
|
2015-06-09 09:15:44 +02:00
|
|
|
}
|
|
|
|
|
2016-06-17 05:06:56 +02:00
|
|
|
static PixmapDirtyUpdatePtr
|
|
|
|
ms_dirty_get_ent(ScreenPtr screen, PixmapPtr slave_dst)
|
|
|
|
{
|
|
|
|
PixmapDirtyUpdatePtr ent;
|
|
|
|
|
|
|
|
if (xorg_list_is_empty(&screen->pixmap_dirty_list))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
|
|
|
|
if (ent->slave_dst == slave_dst)
|
|
|
|
return ent;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
static void
|
2015-09-01 20:20:04 +02:00
|
|
|
msBlockHandler(ScreenPtr pScreen, void *timeout)
|
2011-09-29 13:38:26 +02:00
|
|
|
{
|
2012-05-23 12:21:55 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
|
2011-09-29 13:38:26 +02:00
|
|
|
|
|
|
|
pScreen->BlockHandler = ms->BlockHandler;
|
2015-09-01 20:20:04 +02:00
|
|
|
pScreen->BlockHandler(pScreen, timeout);
|
2015-01-23 07:28:34 +01:00
|
|
|
ms->BlockHandler = pScreen->BlockHandler;
|
2011-09-29 13:38:26 +02:00
|
|
|
pScreen->BlockHandler = msBlockHandler;
|
2015-06-10 05:41:02 +02:00
|
|
|
if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode)
|
2012-07-19 06:12:59 +02:00
|
|
|
dispatch_slave_dirty(pScreen);
|
2014-08-26 20:21:24 +02:00
|
|
|
else if (ms->dirty_enabled)
|
2012-07-19 06:12:59 +02:00
|
|
|
dispatch_dirty(pScreen);
|
2015-06-09 09:15:44 +02:00
|
|
|
|
2016-09-15 14:35:52 +02:00
|
|
|
ms_dirty_update(pScreen, timeout);
|
2011-09-29 13:38:26 +02:00
|
|
|
}
|
|
|
|
|
2016-05-02 22:54:57 +02:00
|
|
|
static void
|
2015-09-01 20:20:04 +02:00
|
|
|
msBlockHandler_oneshot(ScreenPtr pScreen, void *pTimeout)
|
2016-05-02 22:54:57 +02:00
|
|
|
{
|
|
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
|
|
|
|
2015-09-01 20:20:04 +02:00
|
|
|
msBlockHandler(pScreen, pTimeout);
|
2016-05-02 22:54:57 +02:00
|
|
|
|
|
|
|
drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE);
|
|
|
|
}
|
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
static void
|
|
|
|
FreeRec(ScrnInfoPtr pScrn)
|
|
|
|
{
|
2013-03-26 15:19:33 +01:00
|
|
|
modesettingPtr ms;
|
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
if (!pScrn)
|
2013-03-26 15:19:33 +01:00
|
|
|
return;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2013-03-26 15:19:33 +01:00
|
|
|
ms = modesettingPTR(pScrn);
|
|
|
|
if (!ms)
|
|
|
|
return;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2013-03-26 15:19:33 +01:00
|
|
|
if (ms->fd > 0) {
|
2015-07-22 04:56:13 +02:00
|
|
|
modesettingEntPtr ms_ent;
|
2013-03-26 15:19:33 +01:00
|
|
|
int ret;
|
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
ms_ent = ms_ent_priv(pScrn);
|
|
|
|
ms_ent->fd_ref--;
|
|
|
|
if (!ms_ent->fd_ref) {
|
|
|
|
if (ms->pEnt->location.type == BUS_PCI)
|
|
|
|
ret = drmClose(ms->fd);
|
|
|
|
else
|
2018-03-04 22:00:05 +01:00
|
|
|
#ifdef XF86_PDEV_SERVER_FD
|
2015-07-22 04:56:13 +02:00
|
|
|
if (!(ms->pEnt->location.type == BUS_PLATFORM &&
|
|
|
|
(ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
|
2018-03-04 22:00:05 +01:00
|
|
|
#endif
|
2015-07-22 04:56:13 +02:00
|
|
|
ret = close(ms->fd);
|
|
|
|
(void) ret;
|
|
|
|
ms_ent->fd = 0;
|
|
|
|
}
|
2013-03-26 15:19:33 +01:00
|
|
|
}
|
2016-04-29 06:01:31 +02:00
|
|
|
pScrn->driverPrivate = NULL;
|
2015-07-22 04:56:13 +02:00
|
|
|
free(ms->drmmode.Options);
|
2013-03-26 15:19:33 +01:00
|
|
|
free(ms);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-02-10 18:41:44 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
load_glamor(ScrnInfoPtr pScrn)
|
2019-11-18 22:46:44 +01:00
|
|
|
{
|
2020-02-10 18:41:44 +01:00
|
|
|
void *mod = xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME);
|
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
|
|
|
|
|
|
|
if (!mod)
|
|
|
|
return FALSE;
|
|
|
|
|
2019-11-18 22:46:44 +01:00
|
|
|
ms->glamor.back_pixmap_from_fd = LoaderSymbolFromModule(mod, "glamor_back_pixmap_from_fd");
|
|
|
|
ms->glamor.block_handler = LoaderSymbolFromModule(mod, "glamor_block_handler");
|
2019-11-22 18:32:38 +01:00
|
|
|
ms->glamor.clear_pixmap = LoaderSymbolFromModule(mod, "glamor_clear_pixmap");
|
2019-11-18 22:46:44 +01:00
|
|
|
ms->glamor.egl_create_textured_pixmap = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap");
|
|
|
|
ms->glamor.egl_create_textured_pixmap_from_gbm_bo = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap_from_gbm_bo");
|
|
|
|
ms->glamor.egl_exchange_buffers = LoaderSymbolFromModule(mod, "glamor_egl_exchange_buffers");
|
|
|
|
ms->glamor.egl_get_gbm_device = LoaderSymbolFromModule(mod, "glamor_egl_get_gbm_device");
|
|
|
|
ms->glamor.egl_init = LoaderSymbolFromModule(mod, "glamor_egl_init");
|
|
|
|
ms->glamor.finish = LoaderSymbolFromModule(mod, "glamor_finish");
|
|
|
|
ms->glamor.gbm_bo_from_pixmap = LoaderSymbolFromModule(mod, "glamor_gbm_bo_from_pixmap");
|
|
|
|
ms->glamor.init = LoaderSymbolFromModule(mod, "glamor_init");
|
|
|
|
ms->glamor.name_from_pixmap = LoaderSymbolFromModule(mod, "glamor_name_from_pixmap");
|
|
|
|
ms->glamor.set_drawable_modifiers_func = LoaderSymbolFromModule(mod, "glamor_set_drawable_modifiers_func");
|
|
|
|
ms->glamor.shareable_fd_from_pixmap = LoaderSymbolFromModule(mod, "glamor_shareable_fd_from_pixmap");
|
|
|
|
ms->glamor.supports_pixmap_import_export = LoaderSymbolFromModule(mod, "glamor_supports_pixmap_import_export");
|
|
|
|
ms->glamor.xv_init = LoaderSymbolFromModule(mod, "glamor_xv_init");
|
2019-11-22 08:03:50 +01:00
|
|
|
ms->glamor.egl_get_driver_name = LoaderSymbolFromModule(mod, "glamor_egl_get_driver_name");
|
2020-02-10 18:41:44 +01:00
|
|
|
|
|
|
|
return TRUE;
|
2019-11-18 22:46:44 +01:00
|
|
|
}
|
|
|
|
|
2020-02-10 18:41:44 +01:00
|
|
|
#endif
|
|
|
|
|
2013-12-28 20:32:10 +01:00
|
|
|
static void
|
|
|
|
try_enable_glamor(ScrnInfoPtr pScrn)
|
|
|
|
{
|
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
2015-07-22 04:56:13 +02:00
|
|
|
const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options,
|
2013-12-28 20:32:10 +01:00
|
|
|
OPTION_ACCEL_METHOD);
|
|
|
|
Bool do_glamor = (!accel_method_str ||
|
|
|
|
strcmp(accel_method_str, "glamor") == 0);
|
|
|
|
|
2014-11-28 11:20:47 +01:00
|
|
|
ms->drmmode.glamor = FALSE;
|
2013-12-28 20:32:10 +01:00
|
|
|
|
2017-05-16 20:37:14 +02:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
2015-07-22 18:14:06 +02:00
|
|
|
if (ms->drmmode.force_24_32) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cannot use glamor with 24bpp packed fb\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-28 20:32:10 +01:00
|
|
|
if (!do_glamor) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-10 18:41:44 +01:00
|
|
|
if (load_glamor(pScrn)) {
|
2019-11-18 22:46:44 +01:00
|
|
|
if (ms->glamor.egl_init(pScrn, ms->fd)) {
|
2013-12-28 20:32:10 +01:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n");
|
2014-11-28 11:20:47 +01:00
|
|
|
ms->drmmode.glamor = TRUE;
|
2013-12-28 20:32:10 +01:00
|
|
|
} else {
|
2019-09-27 17:43:52 +02:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
2013-12-28 20:32:10 +01:00
|
|
|
"glamor initialization failed\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Failed to load glamor module.\n");
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (do_glamor) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
|
|
"No glamor support in the X Server\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-07-22 18:14:08 +02:00
|
|
|
static Bool
|
|
|
|
msShouldDoubleShadow(ScrnInfoPtr pScrn, modesettingPtr ms)
|
|
|
|
{
|
|
|
|
Bool ret = FALSE, asked;
|
|
|
|
int from;
|
|
|
|
drmVersionPtr v = drmGetVersion(ms->fd);
|
|
|
|
|
|
|
|
if (!ms->drmmode.shadow_enable)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!strcmp(v->name, "mgag200") ||
|
|
|
|
!strcmp(v->name, "ast")) /* XXX || rn50 */
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
drmFreeVersion(v);
|
|
|
|
|
|
|
|
asked = xf86GetOptValBool(ms->drmmode.Options, OPTION_DOUBLE_SHADOW, &ret);
|
|
|
|
|
|
|
|
if (asked)
|
|
|
|
from = X_CONFIG;
|
|
|
|
else
|
|
|
|
from = X_INFO;
|
|
|
|
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, from,
|
|
|
|
"Double-buffered shadow updates: %s\n", ret ? "on" : "off");
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
static Bool
|
2015-07-22 04:56:13 +02:00
|
|
|
ms_get_drm_master_fd(ScrnInfoPtr pScrn)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
EntityInfoPtr pEnt;
|
2015-07-22 04:56:13 +02:00
|
|
|
modesettingPtr ms;
|
|
|
|
modesettingEntPtr ms_ent;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
|
|
|
ms = modesettingPTR(pScrn);
|
2015-07-22 04:56:13 +02:00
|
|
|
ms_ent = ms_ent_priv(pScrn);
|
2008-05-28 16:55:36 +02:00
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
pEnt = ms->pEnt;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
if (ms_ent->fd) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
|
|
" reusing fd for second head\n");
|
|
|
|
ms->fd = ms_ent->fd;
|
|
|
|
ms_ent->fd_ref++;
|
|
|
|
return TRUE;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
2018-01-19 03:07:29 +01:00
|
|
|
ms->fd_passed = FALSE;
|
|
|
|
if ((ms->fd = get_passed_fd()) >= 0) {
|
|
|
|
ms->fd_passed = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-04-26 01:03:00 +02:00
|
|
|
#ifdef XSERVER_PLATFORM_BUS
|
2012-06-05 15:43:21 +02:00
|
|
|
if (pEnt->location.type == BUS_PLATFORM) {
|
2018-03-04 22:00:05 +01:00
|
|
|
#ifdef XF86_PDEV_SERVER_FD
|
2014-03-18 15:48:22 +01:00
|
|
|
if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)
|
2014-10-08 09:39:15 +02:00
|
|
|
ms->fd =
|
|
|
|
xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
|
|
|
|
fd;
|
2014-03-18 15:48:22 +01:00
|
|
|
else
|
2018-03-04 22:00:05 +01:00
|
|
|
#endif
|
2014-03-18 15:48:22 +01:00
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
char *path =
|
|
|
|
xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
|
|
|
|
path;
|
2014-03-18 15:48:22 +01:00
|
|
|
ms->fd = open_hw(path);
|
|
|
|
}
|
2012-06-05 15:43:21 +02:00
|
|
|
}
|
2014-10-08 09:39:15 +02:00
|
|
|
else
|
2012-06-05 15:43:21 +02:00
|
|
|
#endif
|
2017-04-26 01:03:00 +02:00
|
|
|
#ifdef XSERVER_LIBPCIACCESS
|
2012-06-05 15:43:21 +02:00
|
|
|
if (pEnt->location.type == BUS_PCI) {
|
2017-01-10 11:51:57 +01:00
|
|
|
char *BusID = NULL;
|
|
|
|
struct pci_device *PciInfo;
|
|
|
|
|
|
|
|
PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
|
|
|
|
if (PciInfo) {
|
2017-06-26 18:43:54 +02:00
|
|
|
if ((BusID = ms_DRICreatePCIBusID(PciInfo)) != NULL) {
|
|
|
|
ms->fd = drmOpen(NULL, BusID);
|
|
|
|
free(BusID);
|
|
|
|
}
|
2012-06-05 15:43:21 +02:00
|
|
|
}
|
2014-10-08 09:39:15 +02:00
|
|
|
}
|
2017-01-10 11:51:57 +01:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2015-07-22 04:56:13 +02:00
|
|
|
const char *devicename;
|
2012-06-05 15:43:21 +02:00
|
|
|
devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev");
|
|
|
|
ms->fd = open_hw(devicename);
|
2012-05-01 17:52:18 +02:00
|
|
|
}
|
|
|
|
if (ms->fd < 0)
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2012-05-01 17:52:18 +02:00
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
ms_ent->fd = ms->fd;
|
|
|
|
ms_ent->fd_ref = 1;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
PreInit(ScrnInfoPtr pScrn, int flags)
|
|
|
|
{
|
|
|
|
modesettingPtr ms;
|
|
|
|
rgb defaultWeight = { 0, 0, 0 };
|
|
|
|
EntityInfoPtr pEnt;
|
|
|
|
uint64_t value = 0;
|
|
|
|
int ret;
|
2016-06-14 11:58:01 +02:00
|
|
|
int bppflags, connector_count;
|
2015-07-22 04:56:13 +02:00
|
|
|
int defaultdepth, defaultbpp;
|
|
|
|
|
|
|
|
if (pScrn->numEntities != 1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (flags & PROBE_DETECT) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate driverPrivate */
|
|
|
|
if (!GetRec(pScrn))
|
|
|
|
return FALSE;
|
|
|
|
|
2018-09-12 02:56:40 +02:00
|
|
|
pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
|
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
ms = modesettingPTR(pScrn);
|
|
|
|
ms->SaveGeneration = -1;
|
|
|
|
ms->pEnt = pEnt;
|
|
|
|
ms->drmmode.is_secondary = FALSE;
|
|
|
|
pScrn->displayWidth = 640; /* default it */
|
|
|
|
|
|
|
|
if (xf86IsEntityShared(pScrn->entityList[0])) {
|
|
|
|
if (xf86IsPrimInitDone(pScrn->entityList[0]))
|
|
|
|
ms->drmmode.is_secondary = TRUE;
|
|
|
|
else
|
|
|
|
xf86SetPrimInitDone(pScrn->entityList[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pScrn->monitor = pScrn->confScreen->monitor;
|
|
|
|
pScrn->progClock = TRUE;
|
|
|
|
pScrn->rgbBits = 8;
|
|
|
|
|
|
|
|
if (!ms_get_drm_master_fd(pScrn))
|
|
|
|
return FALSE;
|
2012-05-01 18:12:29 +02:00
|
|
|
ms->drmmode.fd = ms->fd;
|
|
|
|
|
2016-06-14 11:58:01 +02:00
|
|
|
if (!check_outputs(ms->fd, &connector_count))
|
|
|
|
return FALSE;
|
|
|
|
|
2012-05-01 18:12:29 +02:00
|
|
|
drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp);
|
2015-07-22 18:14:06 +02:00
|
|
|
if (defaultdepth == 24 && defaultbpp == 24) {
|
|
|
|
ms->drmmode.force_24_32 = TRUE;
|
|
|
|
ms->drmmode.kbpp = 24;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
|
|
"Using 24bpp hw front buffer with 32bpp shadow\n");
|
|
|
|
defaultbpp = 32;
|
|
|
|
} else {
|
2016-12-22 15:41:06 +01:00
|
|
|
ms->drmmode.kbpp = 0;
|
2015-07-22 18:14:06 +02:00
|
|
|
}
|
|
|
|
bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2008-06-26 23:27:44 +02:00
|
|
|
if (!xf86SetDepthBpp
|
2014-10-08 09:39:15 +02:00
|
|
|
(pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags))
|
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
|
|
|
switch (pScrn->depth) {
|
|
|
|
case 15:
|
|
|
|
case 16:
|
|
|
|
case 24:
|
2018-02-27 03:05:32 +01:00
|
|
|
case 30:
|
2014-10-08 09:39:15 +02:00
|
|
|
break;
|
2008-05-28 16:55:36 +02:00
|
|
|
default:
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Given depth (%d) is not supported by the driver\n",
|
|
|
|
pScrn->depth);
|
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
|
|
|
xf86PrintDepthBpp(pScrn);
|
2016-12-22 15:41:06 +01:00
|
|
|
if (!ms->drmmode.kbpp)
|
|
|
|
ms->drmmode.kbpp = pScrn->bitsPerPixel;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
|
|
|
/* Process the options */
|
|
|
|
xf86CollectOptions(pScrn, NULL);
|
2015-07-22 04:56:13 +02:00
|
|
|
if (!(ms->drmmode.Options = malloc(sizeof(Options))))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2015-07-22 04:56:13 +02:00
|
|
|
memcpy(ms->drmmode.Options, Options, sizeof(Options));
|
|
|
|
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options);
|
2008-05-28 16:55:36 +02:00
|
|
|
|
2011-10-05 16:12:43 +02:00
|
|
|
if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2011-10-05 16:12:43 +02:00
|
|
|
if (!xf86SetDefaultVisual(pScrn, -1))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2011-10-05 16:12:43 +02:00
|
|
|
|
2015-07-22 04:56:13 +02:00
|
|
|
if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) {
|
2014-10-08 09:39:15 +02:00
|
|
|
ms->drmmode.sw_cursor = TRUE;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
2014-02-12 19:06:51 +01:00
|
|
|
ms->cursor_width = 64;
|
|
|
|
ms->cursor_height = 64;
|
|
|
|
ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value);
|
|
|
|
if (!ret) {
|
2014-10-08 09:39:15 +02:00
|
|
|
ms->cursor_width = value;
|
2014-02-12 19:06:51 +01:00
|
|
|
}
|
|
|
|
ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value);
|
|
|
|
if (!ret) {
|
2014-10-08 09:39:15 +02:00
|
|
|
ms->cursor_height = value;
|
2014-02-12 19:06:51 +01:00
|
|
|
}
|
|
|
|
|
2013-12-28 20:32:10 +01:00
|
|
|
try_enable_glamor(pScrn);
|
|
|
|
|
2016-06-17 05:06:51 +02:00
|
|
|
if (!ms->drmmode.glamor) {
|
2013-12-28 20:32:10 +01:00
|
|
|
Bool prefer_shadow = TRUE;
|
|
|
|
|
2015-07-22 18:14:06 +02:00
|
|
|
if (ms->drmmode.force_24_32) {
|
|
|
|
prefer_shadow = TRUE;
|
|
|
|
ms->drmmode.shadow_enable = TRUE;
|
|
|
|
} else {
|
|
|
|
ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value);
|
|
|
|
if (!ret) {
|
|
|
|
prefer_shadow = !!value;
|
|
|
|
}
|
2013-12-28 20:32:10 +01:00
|
|
|
|
2015-07-22 18:14:06 +02:00
|
|
|
ms->drmmode.shadow_enable =
|
|
|
|
xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB,
|
|
|
|
prefer_shadow);
|
|
|
|
}
|
2013-12-28 20:32:10 +01:00
|
|
|
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
|
|
"ShadowFB: preferred %s, enabled %s\n",
|
|
|
|
prefer_shadow ? "YES" : "NO",
|
2015-07-22 18:14:06 +02:00
|
|
|
ms->drmmode.force_24_32 ? "FORCE" :
|
2013-12-28 20:32:10 +01:00
|
|
|
ms->drmmode.shadow_enable ? "YES" : "NO");
|
2015-07-22 18:14:08 +02:00
|
|
|
|
|
|
|
ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms);
|
2013-12-28 20:32:10 +01:00
|
|
|
}
|
2011-09-29 16:55:36 +02:00
|
|
|
|
2016-06-17 05:06:51 +02:00
|
|
|
ms->drmmode.pageflip =
|
|
|
|
xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE);
|
|
|
|
|
2016-04-29 06:01:33 +02:00
|
|
|
pScrn->capabilities = 0;
|
|
|
|
ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value);
|
|
|
|
if (ret == 0) {
|
2016-06-14 11:58:01 +02:00
|
|
|
if (connector_count && (value & DRM_PRIME_CAP_IMPORT)) {
|
2016-04-29 06:01:33 +02:00
|
|
|
pScrn->capabilities |= RR_Capability_SinkOutput;
|
|
|
|
if (ms->drmmode.glamor)
|
2016-06-16 15:21:03 +02:00
|
|
|
pScrn->capabilities |= RR_Capability_SinkOffload;
|
2016-04-29 06:01:33 +02:00
|
|
|
}
|
2017-04-26 01:03:00 +02:00
|
|
|
#ifdef GLAMOR_HAS_GBM_LINEAR
|
2016-04-29 06:01:33 +02:00
|
|
|
if (value & DRM_PRIME_CAP_EXPORT && ms->drmmode.glamor)
|
2016-06-16 15:21:03 +02:00
|
|
|
pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
|
2016-04-29 06:01:33 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-04-25 11:46:41 +02:00
|
|
|
if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_ATOMIC, FALSE)) {
|
|
|
|
ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
|
|
|
ms->atomic_modeset = (ret == 0);
|
|
|
|
} else {
|
|
|
|
ms->atomic_modeset = FALSE;
|
|
|
|
}
|
2018-02-28 02:19:37 +01:00
|
|
|
|
2018-04-20 19:59:40 +02:00
|
|
|
ms->kms_has_modifiers = FALSE;
|
|
|
|
ret = drmGetCap(ms->fd, DRM_CAP_ADDFB2_MODIFIERS, &value);
|
|
|
|
if (ret == 0 && value != 0)
|
|
|
|
ms->kms_has_modifiers = TRUE;
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n");
|
|
|
|
goto fail;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
/*
|
|
|
|
* If the driver can do gamma correction, it should call xf86SetGamma() here.
|
|
|
|
*/
|
|
|
|
{
|
2014-10-08 09:39:15 +02:00
|
|
|
Gamma zeros = { 0.0, 0.0, 0.0 };
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
if (!xf86SetGamma(pScrn, zeros)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2016-06-14 11:58:01 +02:00
|
|
|
if (!(pScrn->is_gpu && connector_count == 0) && pScrn->modes == NULL) {
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
|
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
pScrn->currentMode = pScrn->modes;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
/* Set display resolution */
|
|
|
|
xf86SetDpi(pScrn, 0, 0);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
/* Load the required sub modules */
|
|
|
|
if (!xf86LoadSubModule(pScrn, "fb")) {
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2012-02-20 12:00:56 +01:00
|
|
|
if (ms->drmmode.shadow_enable) {
|
2019-10-08 18:52:28 +02:00
|
|
|
void *mod = xf86LoadSubModule(pScrn, "shadow");
|
|
|
|
|
|
|
|
if (!mod)
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2019-10-08 18:52:28 +02:00
|
|
|
|
|
|
|
ms->shadow.Setup = LoaderSymbolFromModule(mod, "shadowSetup");
|
|
|
|
ms->shadow.Add = LoaderSymbolFromModule(mod, "shadowAdd");
|
|
|
|
ms->shadow.Remove = LoaderSymbolFromModule(mod, "shadowRemove");
|
|
|
|
ms->shadow.Update32to24 = LoaderSymbolFromModule(mod, "shadowUpdate32to24");
|
|
|
|
ms->shadow.UpdatePacked = LoaderSymbolFromModule(mod, "shadowUpdatePacked");
|
2011-09-29 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
return TRUE;
|
2014-10-08 09:39:15 +02:00
|
|
|
fail:
|
2011-09-29 12:49:26 +02:00
|
|
|
return FALSE;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
2011-09-29 16:55:36 +02:00
|
|
|
static void *
|
|
|
|
msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
|
2014-10-08 09:39:15 +02:00
|
|
|
CARD32 *size, void *closure)
|
2011-09-29 16:55:36 +02:00
|
|
|
{
|
2012-05-23 12:21:55 +02:00
|
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
|
2011-09-29 16:55:36 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
|
|
|
int stride;
|
|
|
|
|
2015-07-22 18:14:06 +02:00
|
|
|
stride = (pScrn->displayWidth * ms->drmmode.kbpp) / 8;
|
2011-09-29 16:55:36 +02:00
|
|
|
*size = stride;
|
|
|
|
|
2014-12-10 00:20:44 +01:00
|
|
|
return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset);
|
2011-09-29 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
2015-07-22 18:14:08 +02:00
|
|
|
/* somewhat arbitrary tile size, in pixels */
|
|
|
|
#define TILE 16
|
|
|
|
|
|
|
|
static int
|
|
|
|
msUpdateIntersect(modesettingPtr ms, shadowBufPtr pBuf, BoxPtr box,
|
|
|
|
xRectangle *prect)
|
|
|
|
{
|
|
|
|
int i, dirty = 0, stride = pBuf->pPixmap->devKind, cpp = ms->drmmode.cpp;
|
|
|
|
int width = (box->x2 - box->x1) * cpp;
|
|
|
|
unsigned char *old, *new;
|
|
|
|
|
|
|
|
old = ms->drmmode.shadow_fb2;
|
|
|
|
old += (box->y1 * stride) + (box->x1 * cpp);
|
|
|
|
new = ms->drmmode.shadow_fb;
|
|
|
|
new += (box->y1 * stride) + (box->x1 * cpp);
|
|
|
|
|
|
|
|
for (i = box->y2 - box->y1 - 1; i >= 0; i--) {
|
|
|
|
unsigned char *o = old + i * stride,
|
|
|
|
*n = new + i * stride;
|
|
|
|
if (memcmp(o, n, width) != 0) {
|
|
|
|
dirty = 1;
|
|
|
|
memcpy(o, n, width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dirty) {
|
|
|
|
prect->x = box->x1;
|
|
|
|
prect->y = box->y1;
|
|
|
|
prect->width = box->x2 - box->x1;
|
|
|
|
prect->height = box->y2 - box->y1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dirty;
|
|
|
|
}
|
|
|
|
|
2014-05-21 16:16:39 +02:00
|
|
|
static void
|
|
|
|
msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
|
|
|
|
{
|
2015-07-22 18:14:08 +02:00
|
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
2016-12-09 20:52:35 +01:00
|
|
|
Bool use_3224 = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32;
|
2015-07-22 18:14:08 +02:00
|
|
|
|
|
|
|
if (ms->drmmode.shadow_enable2 && ms->drmmode.shadow_fb2) do {
|
|
|
|
RegionPtr damage = DamageRegion(pBuf->pDamage), tiles;
|
|
|
|
BoxPtr extents = RegionExtents(damage);
|
|
|
|
xRectangle *prect;
|
|
|
|
int nrects;
|
|
|
|
int i, j, tx1, tx2, ty1, ty2;
|
|
|
|
|
|
|
|
tx1 = extents->x1 / TILE;
|
|
|
|
tx2 = (extents->x2 + TILE - 1) / TILE;
|
|
|
|
ty1 = extents->y1 / TILE;
|
|
|
|
ty2 = (extents->y2 + TILE - 1) / TILE;
|
|
|
|
|
|
|
|
nrects = (tx2 - tx1) * (ty2 - ty1);
|
|
|
|
if (!(prect = calloc(nrects, sizeof(xRectangle))))
|
|
|
|
break;
|
|
|
|
|
|
|
|
nrects = 0;
|
|
|
|
for (j = ty2 - 1; j >= ty1; j--) {
|
|
|
|
for (i = tx2 - 1; i >= tx1; i--) {
|
|
|
|
BoxRec box;
|
|
|
|
|
|
|
|
box.x1 = max(i * TILE, extents->x1);
|
|
|
|
box.y1 = max(j * TILE, extents->y1);
|
|
|
|
box.x2 = min((i+1) * TILE, extents->x2);
|
|
|
|
box.y2 = min((j+1) * TILE, extents->y2);
|
|
|
|
|
|
|
|
if (RegionContainsRect(damage, &box) != rgnOUT) {
|
|
|
|
if (msUpdateIntersect(ms, pBuf, &box, prect + nrects)) {
|
|
|
|
nrects++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tiles = RegionFromRects(nrects, prect, CT_NONE);
|
|
|
|
RegionIntersect(damage, damage, tiles);
|
|
|
|
RegionDestroy(tiles);
|
|
|
|
free(prect);
|
|
|
|
} while (0);
|
|
|
|
|
2016-12-09 20:52:35 +01:00
|
|
|
if (use_3224)
|
2019-10-08 18:52:28 +02:00
|
|
|
ms->shadow.Update32to24(pScreen, pBuf);
|
2015-07-22 18:14:08 +02:00
|
|
|
else
|
2019-10-08 18:52:28 +02:00
|
|
|
ms->shadow.UpdatePacked(pScreen, pBuf);
|
2014-05-21 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
static Bool
|
|
|
|
msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back)
|
|
|
|
{
|
|
|
|
ScreenPtr screen = crtc->pScreen;
|
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
modesetting: Blacklist USB transport devices from PRIME sync
UDL (USB 2.0 DisplayLink DRM driver) and other drivers for USB transport devices
have strange semantics when it comes to vblank events, due to their inability to
get the actual vblank info.
When doing a page flip, UDL instantly raises a vblank event without waiting for
vblank. It also has no support for DRM_IOCTL_WAIT_VBLANK, and has some strange
behavior with how it handles damage when page flipping.
It's possible to get something semi-working by hacking around these issues,
but even then there isn't much value-add vs single buffered PRIME, and it
reduces maintainability and adds additional risks to the modesetting driver
when running with more well-behaved DRM drivers.
Work needs to be done on UDL in order to properly support synchronized
PRIME. For now, just blacklist it, causing RandR to fall back to
unsynchronized PRIME.
This patch originally blacklisted UDL by name, but it was pointed out that there
are other USB transport device drivers with similar limitations, so it was
expanded to blacklist all USB transport devices.
v1: N/A
v2: N/A
v3: Initial commit
v4: Move check to driver.c for consistency/visibility
v5: Refactor to accomodate earlier changes
v6: Rebase onto ToT
v7: Expand to blacklist all USB transport devices, not just UDL
Signed-off-by: Alex Goins <agoins@nvidia.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
2016-06-17 05:06:54 +02:00
|
|
|
EntityInfoPtr pEnt = ms->pEnt;
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
xf86CrtcPtr xf86Crtc = crtc->devPrivate;
|
|
|
|
|
|
|
|
if (!xf86Crtc)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Not supported if we can't flip */
|
|
|
|
if (!ms->drmmode.pageflip)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Not currently supported with reverse PRIME */
|
|
|
|
if (ms->drmmode.reverse_prime_offload_mode)
|
|
|
|
return FALSE;
|
|
|
|
|
2017-04-26 01:03:00 +02:00
|
|
|
#ifdef XSERVER_PLATFORM_BUS
|
modesetting: Blacklist USB transport devices from PRIME sync
UDL (USB 2.0 DisplayLink DRM driver) and other drivers for USB transport devices
have strange semantics when it comes to vblank events, due to their inability to
get the actual vblank info.
When doing a page flip, UDL instantly raises a vblank event without waiting for
vblank. It also has no support for DRM_IOCTL_WAIT_VBLANK, and has some strange
behavior with how it handles damage when page flipping.
It's possible to get something semi-working by hacking around these issues,
but even then there isn't much value-add vs single buffered PRIME, and it
reduces maintainability and adds additional risks to the modesetting driver
when running with more well-behaved DRM drivers.
Work needs to be done on UDL in order to properly support synchronized
PRIME. For now, just blacklist it, causing RandR to fall back to
unsynchronized PRIME.
This patch originally blacklisted UDL by name, but it was pointed out that there
are other USB transport device drivers with similar limitations, so it was
expanded to blacklist all USB transport devices.
v1: N/A
v2: N/A
v3: Initial commit
v4: Move check to driver.c for consistency/visibility
v5: Refactor to accomodate earlier changes
v6: Rebase onto ToT
v7: Expand to blacklist all USB transport devices, not just UDL
Signed-off-by: Alex Goins <agoins@nvidia.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
2016-06-17 05:06:54 +02:00
|
|
|
if (pEnt->location.type == BUS_PLATFORM) {
|
|
|
|
char *syspath =
|
|
|
|
xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
|
|
|
|
syspath;
|
|
|
|
|
|
|
|
/* Not supported for devices using USB transport due to misbehaved
|
|
|
|
* vblank events */
|
|
|
|
if (syspath && strstr(syspath, "usb"))
|
|
|
|
return FALSE;
|
2017-07-06 14:51:11 +02:00
|
|
|
|
|
|
|
/* EVDI uses USB transport but is platform device, not usb.
|
2020-07-05 22:07:33 +02:00
|
|
|
* Exclude it explicitly. */
|
2017-07-06 14:51:11 +02:00
|
|
|
if (syspath && strstr(syspath, "evdi"))
|
|
|
|
return FALSE;
|
modesetting: Blacklist USB transport devices from PRIME sync
UDL (USB 2.0 DisplayLink DRM driver) and other drivers for USB transport devices
have strange semantics when it comes to vblank events, due to their inability to
get the actual vblank info.
When doing a page flip, UDL instantly raises a vblank event without waiting for
vblank. It also has no support for DRM_IOCTL_WAIT_VBLANK, and has some strange
behavior with how it handles damage when page flipping.
It's possible to get something semi-working by hacking around these issues,
but even then there isn't much value-add vs single buffered PRIME, and it
reduces maintainability and adds additional risks to the modesetting driver
when running with more well-behaved DRM drivers.
Work needs to be done on UDL in order to properly support synchronized
PRIME. For now, just blacklist it, causing RandR to fall back to
unsynchronized PRIME.
This patch originally blacklisted UDL by name, but it was pointed out that there
are other USB transport device drivers with similar limitations, so it was
expanded to blacklist all USB transport devices.
v1: N/A
v2: N/A
v3: Initial commit
v4: Move check to driver.c for consistency/visibility
v5: Refactor to accomodate earlier changes
v6: Rebase onto ToT
v7: Expand to blacklist all USB transport devices, not just UDL
Signed-off-by: Alex Goins <agoins@nvidia.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
2016-06-17 05:06:54 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
return drmmode_EnableSharedPixmapFlipping(xf86Crtc, &ms->drmmode,
|
|
|
|
front, back);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
msDisableSharedPixmapFlipping(RRCrtcPtr crtc)
|
|
|
|
{
|
|
|
|
ScreenPtr screen = crtc->pScreen;
|
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
|
|
|
xf86CrtcPtr xf86Crtc = crtc->devPrivate;
|
|
|
|
|
|
|
|
if (xf86Crtc)
|
|
|
|
drmmode_DisableSharedPixmapFlipping(xf86Crtc, &ms->drmmode);
|
|
|
|
}
|
|
|
|
|
2016-06-17 05:06:56 +02:00
|
|
|
static Bool
|
2017-04-14 12:08:41 +02:00
|
|
|
msStartFlippingPixmapTracking(RRCrtcPtr crtc, DrawablePtr src,
|
2016-06-17 05:06:56 +02:00
|
|
|
PixmapPtr slave_dst1, PixmapPtr slave_dst2,
|
|
|
|
int x, int y, int dst_x, int dst_y,
|
|
|
|
Rotation rotation)
|
|
|
|
{
|
2017-04-14 12:08:41 +02:00
|
|
|
ScreenPtr pScreen = src->pScreen;
|
2016-06-17 05:06:56 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
|
|
|
|
|
2018-08-27 07:37:38 +02:00
|
|
|
msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, slave_dst1->master_pixmap),
|
|
|
|
ppriv2 = msGetPixmapPriv(&ms->drmmode, slave_dst2->master_pixmap);
|
2016-06-17 05:06:56 +02:00
|
|
|
|
|
|
|
if (!PixmapStartDirtyTracking(src, slave_dst1, x, y,
|
|
|
|
dst_x, dst_y, rotation)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PixmapStartDirtyTracking(src, slave_dst2, x, y,
|
|
|
|
dst_x, dst_y, rotation)) {
|
|
|
|
PixmapStopDirtyTracking(src, slave_dst1);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ppriv1->slave_src = src;
|
|
|
|
ppriv2->slave_src = src;
|
|
|
|
|
|
|
|
ppriv1->dirty = ms_dirty_get_ent(pScreen, slave_dst1);
|
|
|
|
ppriv2->dirty = ms_dirty_get_ent(pScreen, slave_dst2);
|
|
|
|
|
|
|
|
ppriv1->defer_dirty_update = TRUE;
|
|
|
|
ppriv2->defer_dirty_update = TRUE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
msPresentSharedPixmap(PixmapPtr slave_dst)
|
|
|
|
{
|
2018-08-27 07:37:38 +02:00
|
|
|
ScreenPtr pScreen = slave_dst->master_pixmap->drawable.pScreen;
|
2016-06-17 05:06:56 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
|
|
|
|
|
2018-08-27 07:37:38 +02:00
|
|
|
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, slave_dst->master_pixmap);
|
2016-06-17 05:06:56 +02:00
|
|
|
|
|
|
|
RegionPtr region = DamageRegion(ppriv->dirty->damage);
|
|
|
|
|
|
|
|
if (RegionNotEmpty(region)) {
|
2017-04-14 12:08:41 +02:00
|
|
|
redisplay_dirty(ppriv->slave_src->pScreen, ppriv->dirty, NULL);
|
2016-06-17 05:06:56 +02:00
|
|
|
DamageEmpty(ppriv->dirty->damage);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
2017-04-14 12:08:41 +02:00
|
|
|
msStopFlippingPixmapTracking(DrawablePtr src,
|
2016-06-17 05:06:56 +02:00
|
|
|
PixmapPtr slave_dst1, PixmapPtr slave_dst2)
|
|
|
|
{
|
2017-04-14 12:08:41 +02:00
|
|
|
ScreenPtr pScreen = src->pScreen;
|
2016-06-17 05:06:56 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
|
|
|
|
|
2018-08-27 07:37:38 +02:00
|
|
|
msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, slave_dst1->master_pixmap),
|
|
|
|
ppriv2 = msGetPixmapPriv(&ms->drmmode, slave_dst2->master_pixmap);
|
2016-06-17 05:06:56 +02:00
|
|
|
|
|
|
|
Bool ret = TRUE;
|
|
|
|
|
|
|
|
ret &= PixmapStopDirtyTracking(src, slave_dst1);
|
|
|
|
ret &= PixmapStopDirtyTracking(src, slave_dst2);
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
ppriv1->slave_src = NULL;
|
|
|
|
ppriv2->slave_src = NULL;
|
|
|
|
|
|
|
|
ppriv1->dirty = NULL;
|
|
|
|
ppriv2->dirty = NULL;
|
|
|
|
|
|
|
|
ppriv1->defer_dirty_update = FALSE;
|
|
|
|
ppriv2->defer_dirty_update = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
static Bool
|
|
|
|
CreateScreenResources(ScreenPtr pScreen)
|
|
|
|
{
|
2012-05-23 12:21:55 +02:00
|
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
2008-05-28 16:55:36 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
2008-06-26 23:27:44 +02:00
|
|
|
PixmapPtr rootPixmap;
|
2008-05-28 16:55:36 +02:00
|
|
|
Bool ret;
|
2014-12-09 21:43:57 +01:00
|
|
|
void *pixels = NULL;
|
2014-12-20 03:40:19 +01:00
|
|
|
int err;
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
pScreen->CreateScreenResources = ms->createScreenResources;
|
|
|
|
ret = pScreen->CreateScreenResources(pScreen);
|
|
|
|
pScreen->CreateScreenResources = CreateScreenResources;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2016-05-02 22:54:57 +02:00
|
|
|
if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, pScrn->is_gpu))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2014-12-10 00:18:39 +01:00
|
|
|
if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode))
|
|
|
|
return FALSE;
|
2013-12-28 20:32:10 +01:00
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
drmmode_uevent_init(pScrn, &ms->drmmode);
|
2008-06-16 16:07:39 +02:00
|
|
|
|
2014-02-25 15:06:55 +01:00
|
|
|
if (!ms->drmmode.sw_cursor)
|
2011-11-03 14:20:18 +01:00
|
|
|
drmmode_map_cursor_bos(pScrn, &ms->drmmode);
|
2014-12-09 21:43:57 +01:00
|
|
|
|
|
|
|
if (!ms->drmmode.gbm) {
|
|
|
|
pixels = drmmode_map_front_bo(&ms->drmmode);
|
|
|
|
if (!pixels)
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-06-26 23:27:44 +02:00
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
rootPixmap = pScreen->GetScreenPixmap(pScreen);
|
2011-09-29 16:55:36 +02:00
|
|
|
|
2012-02-20 12:00:56 +01:00
|
|
|
if (ms->drmmode.shadow_enable)
|
2014-10-08 09:39:15 +02:00
|
|
|
pixels = ms->drmmode.shadow_fb;
|
|
|
|
|
2015-07-22 18:14:08 +02:00
|
|
|
if (ms->drmmode.shadow_enable2) {
|
|
|
|
ms->drmmode.shadow_fb2 = calloc(1, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3));
|
|
|
|
if (!ms->drmmode.shadow_fb2)
|
|
|
|
ms->drmmode.shadow_enable2 = FALSE;
|
|
|
|
}
|
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels))
|
2014-10-08 09:39:15 +02:00
|
|
|
FatalError("Couldn't adjust screen pixmap\n");
|
2008-06-16 16:07:39 +02:00
|
|
|
|
2012-02-20 12:00:56 +01:00
|
|
|
if (ms->drmmode.shadow_enable) {
|
2019-10-08 18:52:28 +02:00
|
|
|
if (!ms->shadow.Add(pScreen, rootPixmap, msUpdatePacked, msShadowWindow,
|
|
|
|
0, 0))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2011-09-29 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
2014-12-20 03:40:19 +01:00
|
|
|
err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0);
|
2011-09-29 13:38:26 +02:00
|
|
|
|
2014-12-20 03:40:19 +01:00
|
|
|
if (err != -EINVAL && err != -ENOSYS) {
|
|
|
|
ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
|
|
|
|
pScreen, rootPixmap);
|
|
|
|
|
|
|
|
if (ms->damage) {
|
|
|
|
DamageRegister(&rootPixmap->drawable, ms->damage);
|
|
|
|
ms->dirty_enabled = TRUE;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Failed to create screen damage record\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-09-29 13:38:26 +02:00
|
|
|
}
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
|
modesetting: Check whether RandR was initialized before calling rrGetScrPriv
Calling rrGetScrPriv when RandR isn't initialized causes an assertion
failure that aborts the server:
Xorg: ../include/privates.h:121: dixGetPrivateAddr: Assertion `key->initialized' failed.
Thread 1 "Xorg" received signal SIGABRT, Aborted.
0x00007ffff78a8f25 in raise () from /usr/lib/libc.so.6
(gdb) bt
#0 0x00007ffff78a8f25 in raise () from /usr/lib/libc.so.6
#1 0x00007ffff7892897 in abort () from /usr/lib/libc.so.6
#2 0x00007ffff7892767 in __assert_fail_base.cold () from /usr/lib/libc.so.6
#3 0x00007ffff78a1526 in __assert_fail () from /usr/lib/libc.so.6
#4 0x00007ffff7fb57c1 in dixGetPrivateAddr (privates=0x555555ab1b60, key=0x555555855720 <rrPrivKeyRec>) at ../include/privates.h:121
#5 0x00007ffff7fb5822 in dixGetPrivate (privates=0x555555ab1b60, key=0x555555855720 <rrPrivKeyRec>) at ../include/privates.h:136
#6 0x00007ffff7fb586a in dixLookupPrivate (privates=0x555555ab1b60, key=0x555555855720 <rrPrivKeyRec>) at ../include/privates.h:166
#7 0x00007ffff7fb8445 in CreateScreenResources (pScreen=0x555555ab1790) at ../hw/xfree86/drivers/modesetting/driver.c:1335
#8 0x000055555576c5e4 in xf86CrtcCreateScreenResources (screen=0x555555ab1790) at ../hw/xfree86/modes/xf86Crtc.c:744
#9 0x00005555555d8bb6 in dix_main (argc=4, argv=0x7fffffffead8, envp=0x7fffffffeb00) at ../dix/main.c:214
#10 0x00005555557a4f0b in main (argc=4, argv=0x7fffffffead8, envp=0x7fffffffeb00) at ../dix/stubmain.c:34
This can happen, for example, if the server is configured with Xinerama
and there is more than one X screen:
Section "ServerLayout"
Identifier "crash"
Screen 0 "modesetting"
Screen 1 "dummy" RightOf "modesetting"
Option "Xinerama"
EndSection
Section "Device"
Identifier "modesetting"
Driver "modesetting"
EndSection
Section "Screen"
Identifier "modesetting"
Device "modesetting"
EndSection
Section "Device"
Identifier "dummy"
Driver "dummy"
EndSection
Section "Screen"
Identifier "dummy"
Device "dummy"
EndSection
The problem does not reproduce if there is only one X screen because of
this code in xf86RandR12Init:
#ifdef PANORAMIX
/* XXX disable RandR when using Xinerama */
if (!noPanoramiXExtension) {
if (xf86NumScreens == 1)
noPanoramiXExtension = TRUE;
else
return TRUE;
}
#endif
Fix the problem by checking dixPrivateKeyRegistered(rrPrivKey) before
calling rrGetScrPriv. This is similar to what the xf86-video-amdgpu
driver does:
https://gitlab.freedesktop.org/xorg/driver/xf86-video-amdgpu/blob/fd66f5c0bea2b7c22a47bfd5eb1f22d32d166d9c/src/amdgpu_kms.c#L388
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
2019-12-26 22:40:17 +01:00
|
|
|
if (dixPrivateKeyRegistered(rrPrivKey)) {
|
|
|
|
rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
|
modesetting: Check whether RandR was initialized before calling rrGetScrPriv
Calling rrGetScrPriv when RandR isn't initialized causes an assertion
failure that aborts the server:
Xorg: ../include/privates.h:121: dixGetPrivateAddr: Assertion `key->initialized' failed.
Thread 1 "Xorg" received signal SIGABRT, Aborted.
0x00007ffff78a8f25 in raise () from /usr/lib/libc.so.6
(gdb) bt
#0 0x00007ffff78a8f25 in raise () from /usr/lib/libc.so.6
#1 0x00007ffff7892897 in abort () from /usr/lib/libc.so.6
#2 0x00007ffff7892767 in __assert_fail_base.cold () from /usr/lib/libc.so.6
#3 0x00007ffff78a1526 in __assert_fail () from /usr/lib/libc.so.6
#4 0x00007ffff7fb57c1 in dixGetPrivateAddr (privates=0x555555ab1b60, key=0x555555855720 <rrPrivKeyRec>) at ../include/privates.h:121
#5 0x00007ffff7fb5822 in dixGetPrivate (privates=0x555555ab1b60, key=0x555555855720 <rrPrivKeyRec>) at ../include/privates.h:136
#6 0x00007ffff7fb586a in dixLookupPrivate (privates=0x555555ab1b60, key=0x555555855720 <rrPrivKeyRec>) at ../include/privates.h:166
#7 0x00007ffff7fb8445 in CreateScreenResources (pScreen=0x555555ab1790) at ../hw/xfree86/drivers/modesetting/driver.c:1335
#8 0x000055555576c5e4 in xf86CrtcCreateScreenResources (screen=0x555555ab1790) at ../hw/xfree86/modes/xf86Crtc.c:744
#9 0x00005555555d8bb6 in dix_main (argc=4, argv=0x7fffffffead8, envp=0x7fffffffeb00) at ../dix/main.c:214
#10 0x00005555557a4f0b in main (argc=4, argv=0x7fffffffead8, envp=0x7fffffffeb00) at ../dix/stubmain.c:34
This can happen, for example, if the server is configured with Xinerama
and there is more than one X screen:
Section "ServerLayout"
Identifier "crash"
Screen 0 "modesetting"
Screen 1 "dummy" RightOf "modesetting"
Option "Xinerama"
EndSection
Section "Device"
Identifier "modesetting"
Driver "modesetting"
EndSection
Section "Screen"
Identifier "modesetting"
Device "modesetting"
EndSection
Section "Device"
Identifier "dummy"
Driver "dummy"
EndSection
Section "Screen"
Identifier "dummy"
Device "dummy"
EndSection
The problem does not reproduce if there is only one X screen because of
this code in xf86RandR12Init:
#ifdef PANORAMIX
/* XXX disable RandR when using Xinerama */
if (!noPanoramiXExtension) {
if (xf86NumScreens == 1)
noPanoramiXExtension = TRUE;
else
return TRUE;
}
#endif
Fix the problem by checking dixPrivateKeyRegistered(rrPrivKey) before
calling rrGetScrPriv. This is similar to what the xf86-video-amdgpu
driver does:
https://gitlab.freedesktop.org/xorg/driver/xf86-video-amdgpu/blob/fd66f5c0bea2b7c22a47bfd5eb1f22d32d166d9c/src/amdgpu_kms.c#L388
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
2019-12-26 22:40:17 +01:00
|
|
|
pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping;
|
|
|
|
pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping;
|
|
|
|
|
|
|
|
pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
|
|
|
|
}
|
2016-06-17 05:06:56 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
return ret;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 09:15:44 +02:00
|
|
|
static Bool
|
2019-12-13 03:18:53 +01:00
|
|
|
msSharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle)
|
2015-06-09 09:15:44 +02:00
|
|
|
{
|
|
|
|
#ifdef GLAMOR_HAS_GBM
|
2019-12-13 03:18:53 +01:00
|
|
|
modesettingPtr ms =
|
|
|
|
modesettingPTR(xf86ScreenToScrn(ppix->drawable.pScreen));
|
2015-06-09 09:15:44 +02:00
|
|
|
int ret;
|
|
|
|
CARD16 stride;
|
|
|
|
CARD32 size;
|
2019-11-18 22:46:44 +01:00
|
|
|
ret = ms->glamor.shareable_fd_from_pixmap(ppix->drawable.pScreen, ppix,
|
|
|
|
&stride, &size);
|
2015-06-09 09:15:44 +02:00
|
|
|
if (ret == -1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
*handle = (void *)(long)(ret);
|
|
|
|
return TRUE;
|
|
|
|
#endif
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-07-19 06:12:59 +02:00
|
|
|
static Bool
|
|
|
|
msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
|
|
|
|
{
|
2017-05-16 20:37:14 +02:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
2012-07-19 06:12:59 +02:00
|
|
|
ScreenPtr screen = ppix->drawable.pScreen;
|
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
|
|
|
Bool ret;
|
2014-10-08 09:39:15 +02:00
|
|
|
int ihandle = (int) (long) fd_handle;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
2016-05-06 02:46:14 +02:00
|
|
|
if (ihandle == -1)
|
|
|
|
if (!ms->drmmode.reverse_prime_offload_mode)
|
|
|
|
return drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, 0, 0);
|
|
|
|
|
2015-06-10 05:41:02 +02:00
|
|
|
if (ms->drmmode.reverse_prime_offload_mode) {
|
2019-11-18 22:46:44 +01:00
|
|
|
ret = ms->glamor.back_pixmap_from_fd(ppix, ihandle,
|
|
|
|
ppix->drawable.width,
|
|
|
|
ppix->drawable.height,
|
|
|
|
ppix->devKind,
|
|
|
|
ppix->drawable.depth,
|
|
|
|
ppix->drawable.bitsPerPixel);
|
2015-06-10 05:41:02 +02:00
|
|
|
} else {
|
|
|
|
int size = ppix->devKind * ppix->drawable.height;
|
|
|
|
ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size);
|
|
|
|
}
|
2012-07-19 06:12:59 +02:00
|
|
|
if (ret == FALSE)
|
2014-10-08 09:39:15 +02:00
|
|
|
return ret;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
|
|
|
return TRUE;
|
2015-07-01 12:41:15 +02:00
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
|
2016-06-17 05:06:56 +02:00
|
|
|
static Bool
|
|
|
|
msRequestSharedPixmapNotifyDamage(PixmapPtr ppix)
|
|
|
|
{
|
|
|
|
ScreenPtr screen = ppix->drawable.pScreen;
|
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
|
|
|
|
2018-08-27 07:37:38 +02:00
|
|
|
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix->master_pixmap);
|
2016-06-17 05:06:56 +02:00
|
|
|
|
|
|
|
ppriv->notify_on_damage = TRUE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
static Bool
|
|
|
|
msSharedPixmapNotifyDamage(PixmapPtr ppix)
|
|
|
|
{
|
|
|
|
Bool ret = FALSE;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
ScreenPtr screen = ppix->drawable.pScreen;
|
|
|
|
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
|
|
|
|
modesettingPtr ms = modesettingPTR(scrn);
|
|
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
|
|
|
|
|
|
|
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
|
|
|
|
|
|
|
|
if (!ppriv->wait_for_damage)
|
|
|
|
return ret;
|
|
|
|
ppriv->wait_for_damage = FALSE;
|
|
|
|
|
|
|
|
for (c = 0; c < xf86_config->num_crtc; c++) {
|
|
|
|
xf86CrtcPtr crtc = xf86_config->crtc[c];
|
|
|
|
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
|
|
|
|
|
|
|
if (!drmmode_crtc)
|
|
|
|
continue;
|
|
|
|
if (!(drmmode_crtc->prime_pixmap && drmmode_crtc->prime_pixmap_back))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Received damage on master screen pixmap, schedule present on vblank
|
|
|
|
ret |= drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, &ms->drmmode);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-18 15:48:22 +01:00
|
|
|
static Bool
|
|
|
|
SetMaster(ScrnInfoPtr pScrn)
|
|
|
|
{
|
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
|
|
|
int ret;
|
|
|
|
|
2018-03-04 22:00:05 +01:00
|
|
|
#ifdef XF86_PDEV_SERVER_FD
|
2014-03-18 15:48:22 +01:00
|
|
|
if (ms->pEnt->location.type == BUS_PLATFORM &&
|
2014-10-08 09:39:15 +02:00
|
|
|
(ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
|
2014-03-18 15:48:22 +01:00
|
|
|
return TRUE;
|
2018-03-04 22:00:05 +01:00
|
|
|
#endif
|
2014-03-18 15:48:22 +01:00
|
|
|
|
2018-01-19 03:07:29 +01:00
|
|
|
if (ms->fd_passed)
|
|
|
|
return TRUE;
|
|
|
|
|
2014-03-18 15:48:22 +01:00
|
|
|
ret = drmSetMaster(ms->fd);
|
|
|
|
if (ret)
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
return ret == 0;
|
|
|
|
}
|
|
|
|
|
2016-05-02 22:54:56 +02:00
|
|
|
/* When the root window is created, initialize the screen contents from
|
|
|
|
* console if -background none was specified on the command line
|
|
|
|
*/
|
|
|
|
static Bool
|
|
|
|
CreateWindow_oneshot(WindowPtr pWin)
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
|
|
|
Bool ret;
|
|
|
|
|
|
|
|
pScreen->CreateWindow = ms->CreateWindow;
|
|
|
|
ret = pScreen->CreateWindow(pWin);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
drmmode_copy_fb(pScrn, &ms->drmmode);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-05-28 14:33:07 +02:00
|
|
|
static Bool
|
2014-08-26 20:37:46 +02:00
|
|
|
ScreenInit(ScreenPtr pScreen, int argc, char **argv)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2012-05-23 12:21:55 +02:00
|
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
2008-05-28 16:55:36 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
|
|
|
VisualPtr visual;
|
|
|
|
|
2008-06-16 16:07:39 +02:00
|
|
|
pScrn->pScreen = pScreen;
|
|
|
|
|
2014-03-18 15:48:22 +01:00
|
|
|
if (!SetMaster(pScrn))
|
2011-09-29 15:05:43 +02:00
|
|
|
return FALSE;
|
2014-03-18 15:48:22 +01:00
|
|
|
|
2014-12-09 21:43:57 +01:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
|
|
|
if (ms->drmmode.glamor)
|
2019-11-18 22:46:44 +01:00
|
|
|
ms->drmmode.gbm = ms->glamor.egl_get_gbm_device(pScreen);
|
2014-12-09 21:43:57 +01:00
|
|
|
#endif
|
|
|
|
|
2008-06-26 23:27:44 +02:00
|
|
|
/* HW dependent - FIXME */
|
|
|
|
pScrn->displayWidth = pScrn->virtualX;
|
2011-09-29 12:49:26 +02:00
|
|
|
if (!drmmode_create_initial_bos(pScrn, &ms->drmmode))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
2012-02-20 12:00:56 +01:00
|
|
|
if (ms->drmmode.shadow_enable) {
|
2014-10-08 09:39:15 +02:00
|
|
|
ms->drmmode.shadow_fb =
|
|
|
|
calloc(1,
|
|
|
|
pScrn->displayWidth * pScrn->virtualY *
|
|
|
|
((pScrn->bitsPerPixel + 7) >> 3));
|
|
|
|
if (!ms->drmmode.shadow_fb)
|
|
|
|
ms->drmmode.shadow_enable = FALSE;
|
|
|
|
}
|
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
miClearVisualTypes();
|
|
|
|
|
|
|
|
if (!miSetVisualTypes(pScrn->depth,
|
2014-10-08 09:39:15 +02:00
|
|
|
miGetDefaultVisualMask(pScrn->depth),
|
|
|
|
pScrn->rgbBits, pScrn->defaultVisual))
|
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
|
|
|
if (!miSetPixmapDepths())
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
2014-10-08 09:39:15 +02:00
|
|
|
if (!dixRegisterScreenSpecificPrivateKey
|
|
|
|
(pScreen, &ms->drmmode.pixmapPrivateKeyRec, PRIVATE_PIXMAP,
|
|
|
|
sizeof(msPixmapPrivRec))) {
|
|
|
|
return FALSE;
|
2012-07-19 06:12:59 +02:00
|
|
|
}
|
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
pScrn->memPhysBase = 0;
|
|
|
|
pScrn->fbOffset = 0;
|
|
|
|
|
2008-06-26 23:27:44 +02:00
|
|
|
if (!fbScreenInit(pScreen, NULL,
|
2014-10-08 09:39:15 +02:00
|
|
|
pScrn->virtualX, pScrn->virtualY,
|
|
|
|
pScrn->xDpi, pScrn->yDpi,
|
|
|
|
pScrn->displayWidth, pScrn->bitsPerPixel))
|
|
|
|
return FALSE;
|
2008-05-28 16:55:36 +02:00
|
|
|
|
|
|
|
if (pScrn->bitsPerPixel > 8) {
|
2014-10-08 09:39:15 +02:00
|
|
|
/* Fixup RGB ordering */
|
|
|
|
visual = pScreen->visuals + pScreen->numVisuals;
|
|
|
|
while (--visual >= pScreen->visuals) {
|
|
|
|
if ((visual->class | DynamicClass) == DirectColor) {
|
|
|
|
visual->offsetRed = pScrn->offset.red;
|
|
|
|
visual->offsetGreen = pScrn->offset.green;
|
|
|
|
visual->offsetBlue = pScrn->offset.blue;
|
|
|
|
visual->redMask = pScrn->mask.red;
|
|
|
|
visual->greenMask = pScrn->mask.green;
|
|
|
|
visual->blueMask = pScrn->mask.blue;
|
|
|
|
}
|
|
|
|
}
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fbPictureInit(pScreen, NULL, 0);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2018-02-28 02:19:44 +01:00
|
|
|
if (drmmode_init(pScrn, &ms->drmmode) == FALSE) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Failed to initialize glamor at ScreenInit() time.\n");
|
|
|
|
return FALSE;
|
2013-12-28 20:32:10 +01:00
|
|
|
}
|
|
|
|
|
2019-10-08 18:52:28 +02:00
|
|
|
if (ms->drmmode.shadow_enable && !ms->shadow.Setup(pScreen)) {
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "shadow fb init failed\n");
|
|
|
|
return FALSE;
|
2011-09-29 16:55:36 +02:00
|
|
|
}
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2008-06-16 16:07:39 +02:00
|
|
|
ms->createScreenResources = pScreen->CreateScreenResources;
|
|
|
|
pScreen->CreateScreenResources = CreateScreenResources;
|
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
xf86SetBlackWhitePixels(pScreen);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
xf86SetBackingStore(pScreen);
|
|
|
|
xf86SetSilkenMouse(pScreen);
|
|
|
|
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2019-06-24 21:46:26 +02:00
|
|
|
/* If pageflip is enabled hook the screen's cursor-sprite (swcursor) funcs.
|
2020-07-05 22:07:33 +02:00
|
|
|
* So that we can disable page-flipping on fallback to a swcursor. */
|
2019-06-24 21:46:26 +02:00
|
|
|
if (ms->drmmode.pageflip) {
|
|
|
|
miPointerScreenPtr PointPriv =
|
|
|
|
dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
|
|
|
|
|
|
|
|
if (!dixRegisterScreenPrivateKey(&ms->drmmode.spritePrivateKeyRec,
|
|
|
|
pScreen, PRIVATE_DEVICE,
|
|
|
|
sizeof(msSpritePrivRec)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ms->SpriteFuncs = PointPriv->spriteFuncs;
|
|
|
|
PointPriv->spriteFuncs = &drmmode_sprite_funcs;
|
|
|
|
}
|
|
|
|
|
2008-06-16 16:07:39 +02:00
|
|
|
/* Need to extend HWcursor support to handle mask interleave */
|
2011-11-14 12:22:44 +01:00
|
|
|
if (!ms->drmmode.sw_cursor)
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86_cursors_init(pScreen, ms->cursor_width, ms->cursor_height,
|
|
|
|
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
|
2015-01-05 08:27:32 +01:00
|
|
|
HARDWARE_CURSOR_UPDATE_UNHIDDEN |
|
2014-10-08 09:39:15 +02:00
|
|
|
HARDWARE_CURSOR_ARGB);
|
2008-05-28 20:59:38 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
/* Must force it before EnterVT, so we are in control of VT and
|
|
|
|
* later memory should be bound when allocating, e.g rotate_mem */
|
|
|
|
pScrn->vtSema = TRUE;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2016-05-02 22:54:56 +02:00
|
|
|
if (serverGeneration == 1 && bgNoneRoot && ms->drmmode.glamor) {
|
|
|
|
ms->CreateWindow = pScreen->CreateWindow;
|
|
|
|
pScreen->CreateWindow = CreateWindow_oneshot;
|
|
|
|
}
|
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
pScreen->SaveScreen = xf86SaveScreen;
|
|
|
|
ms->CloseScreen = pScreen->CloseScreen;
|
|
|
|
pScreen->CloseScreen = CloseScreen;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2011-09-29 13:38:26 +02:00
|
|
|
ms->BlockHandler = pScreen->BlockHandler;
|
2016-05-02 22:54:57 +02:00
|
|
|
pScreen->BlockHandler = msBlockHandler_oneshot;
|
2011-09-29 13:38:26 +02:00
|
|
|
|
2015-06-09 09:15:44 +02:00
|
|
|
pScreen->SharePixmapBacking = msSharePixmapBacking;
|
2012-07-19 06:12:59 +02:00
|
|
|
pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking;
|
2015-06-09 09:15:44 +02:00
|
|
|
pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
|
|
|
|
pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
|
2012-07-19 06:12:59 +02:00
|
|
|
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage;
|
2016-06-17 05:06:56 +02:00
|
|
|
pScreen->RequestSharedPixmapNotifyDamage =
|
|
|
|
msRequestSharedPixmapNotifyDamage;
|
|
|
|
|
|
|
|
pScreen->PresentSharedPixmap = msPresentSharedPixmap;
|
|
|
|
pScreen->StopFlippingPixmapTracking = msStopFlippingPixmapTracking;
|
modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and
double buffering. Allows modesetting driver to be used as a sink with PRIME
synchronization.
Changes dispatch_slave_dirty to flush damage from both scanout pixmaps.
Changes drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows
me to use it to explicitly set both prime_pixmap and prime_pixmap_back
individually. drmmode_set_scanout_pixmap() without the extra parameter
remains to cover the single-buffered case, but only works if we aren't
already double buffered.
driver.c:
Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and
SharedPixmapNotifyDamage.
Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the
same but flushes damage associated with a ppriv instead of the crtc, and
chanage dispatch_slave_dirty to use it on both scanout pixmaps if
applicable.
drmmode_display.h:
Add flip_seq field to msPixmapPrivRec to keep track of the event handler
associated with a given pixmap, if any.
Add wait_for_damage field to msPixmapPrivRec to keep track if we have
requested a damage notification from the source.
Add enable_flipping field to drmmode_crtc_private_rec to keep track if
flipping is enabled or disabled.
Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back
buffer internally.
Add declarations for drmmode_SetupPageFlipFence(),
drmmode_EnableSharedPixmapFlipping(),
drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and
drmmode_SharedPixmapPresentOnVBlank().
Move slave damage from crtc to ppriv.
drmmode_display.c:
Change drmmode_set_scanout_pixmap*() functions to
drmmode_set_target_scanout_pixmap*() that take an additional parameter
PixmapPtr *target for explicitly setting different scanout pixmaps.
Add definitions for functions drmmode_SharedPixmapFlip(),
drmmode_SharedPixmapPresentOnVBlank(),
drmmode_SharedPixmapPresent(),
drmmode_SharedPixmapVBlankEventHandler(),
drmmode_SharedPixmapVBlankEventAbort(),
drmmode_EnableSharedPixmapFlipping(), and
drmmode_DisableSharedPixmapFlipping,
drmmode_InitSharedPixmapFlipping(), and
drmmode_FiniSharedPixmapFlipping, along with struct
vblank_event_args.
The control flow is as follows:
pScrPriv->rrEnableSharedPixmapFlipping() makes its way to
drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to
TRUE and sets both scanout pixmaps prime_pixmap and
prime_pixmap_back.
When setting a mode, if prime_pixmap is defined, modesetting
driver will call drmmode_InitSharedPixmapFlipping(), which if
flipping is enabled will call drmmode_SharedPixmapPresent() on
scanout_pixmap_back.
drmmode_SharedPixmapPresent() requests that for the source to
present on the given buffer using master->PresentSharedPixmap(). If
it succeeds, it will then attempt to flip to that buffer using
drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it
does, it will raise a warning and try drmmode_SharedPixmapPresent()
again on the next vblank using
drmmode_SharedPixmapPresentOnVBlank().
master->PresentSharedPixmap() could fail, in most cases because
there is no outstanding damage on the mscreenpix tracked by the
shared pixmap. In this case, drmmode_SharedPixmapPresent() will
attempt to use master->RequestSharedPixmapNotifyDamage() to request
for the source driver to call slave->SharedPixmapNotifyDamage() in
response to damage on mscreenpix. This will ultimately call
into drmmode_SharedPixmapPresentOnVBlank() to retry
drmmode_SharedPixmapPresent() on the next vblank after
accumulating damage.
drmmode_SharedPixmapFlip() sets up page flip event handler by
packing struct vblank_event_args with the necessary parameters, and
registering drmmode_SharedPixmapVBlankEventHandler() and
drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM
event handler queue. Then, it uses the drmModePageFlip() to flip on
the next vblank and raise an event.
drmmode_SharedPixmapPresentOnVBlank() operates similarly to
drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of
drmModePageFlip() to raise the event without flipping.
On the next vblank, DRM will raise an event that will ultimately be
handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped,
it will update prime_pixmap and prime_pixmap_back to reflect that
frontTarget is now being displayed, and use
drmmode_SharedPixmapPresent(backTarget) to start the process again
on the now-hidden shared pixmap. If we didn't flip, it will just
use drmmode_SharedPixmapPresent(frontTarget) to start the process
again on the still-hidden shared pixmap.
Note that presentation generally happens asynchronously, so with
these changes alone tearing is reduced, but we can't always
guarantee that the present will finish before the flip. These
changes are meant to be paired with changes to the sink DRM driver
that makes flips wait on fences attached to dmabuf backed buffers.
The source driver is responsible for attaching the fences and
signaling them when presentation is finished.
Note that because presentation is requested in response to a
vblank, PRIME sources will now conform to the sink's refresh rate.
At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be
called, making its way to drmmode_FiniSharedPixmapFlipping().
There, the event handlers for prime_pixmap and prime_pixmap_back
are aborted, freeing the left over parameter structure. Then,
prime_pixmap and prime_pixmap back are unset as scanout pixmaps.
Register and tear down slave damage per-scanout pixmap instead of
per-crtc.
v1: Initial commit
v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap
Renamed flipSeq to flip_seq
Warn if flip failed
Use SharedPixmapNotifyDamage to retry on next vblank after damage
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Do damage tracking on both scanout pixmaps
v4: Tweaks to commit message
v5: Revise for internal storage of prime pixmap ptrs
Move disabling for reverse PRIME from source commit to here
Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps
internally to EnableSharedPixmapFlipping().
Don't support flipping if ms->drmmode.pageflip == FALSE.
Move flipping_active check to this commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:52 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
if (!xf86CrtcScreenInit(pScreen))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2017-10-24 00:43:43 +02:00
|
|
|
if (!drmmode_setup_colormap(pScreen, pScrn))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2018-04-04 06:01:14 +02:00
|
|
|
if (ms->atomic_modeset)
|
|
|
|
xf86DPMSInit(pScreen, drmmode_set_dpms, 0);
|
|
|
|
else
|
|
|
|
xf86DPMSInit(pScreen, xf86DPMSSet, 0);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2017-05-16 20:37:14 +02:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
2014-12-14 07:22:30 +01:00
|
|
|
if (ms->drmmode.glamor) {
|
|
|
|
XF86VideoAdaptorPtr glamor_adaptor;
|
|
|
|
|
2019-11-18 22:46:44 +01:00
|
|
|
glamor_adaptor = ms->glamor.xv_init(pScreen, 16);
|
2014-12-14 07:22:30 +01:00
|
|
|
if (glamor_adaptor != NULL)
|
|
|
|
xf86XVScreenInit(pScreen, &glamor_adaptor, 1);
|
|
|
|
else
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Failed to initialize XV support.\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
if (serverGeneration == 1)
|
2014-10-08 09:39:15 +02:00
|
|
|
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
modesetting: Add support for DRI2 with glamor.
This is derived from the intel driver DRI2 code, with swapchain and
pageflipping dropped, functions renamed, and vblank event management
shared code moved to a vblank.c for reuse by Present.
This allows AIGLX to load, which means that you get appropriate
visuals exposed in GL, along with many extensions under
direct-rendering that require presence in GLX (which aren't supported
in glxdriswrast.c).
v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
Drop triple-buffering, which was totally broken in practice (I'll
try to fix this later). Fix up some style nits. Document the
general flow of pageflipping and why, rename the DRI2 frame event
type enums to reflect what they're for, and handle them in a
single switch statement so you can understand the state machine
more easily.
v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
(not that the normal 2D driver is stable with pageflipping for
me), and I won't get it fixed before the merge window. It now
passes all of the OML_sync_control tests from Jamey and Theo
(except for occasional warns in timing -fullscreen -divisor 2).
v4: Fix doxygen at the top of vblank.c
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2013-12-31 02:23:38 +01:00
|
|
|
if (!ms_vblank_screen_init(pScreen)) {
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Failed to initialize vblank support.\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-05-16 20:37:14 +02:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
2014-11-28 11:20:47 +01:00
|
|
|
if (ms->drmmode.glamor) {
|
2018-02-15 13:46:55 +01:00
|
|
|
if (!(ms->drmmode.dri2_enable = ms_dri2_screen_init(pScreen))) {
|
modesetting: Add support for DRI2 with glamor.
This is derived from the intel driver DRI2 code, with swapchain and
pageflipping dropped, functions renamed, and vblank event management
shared code moved to a vblank.c for reuse by Present.
This allows AIGLX to load, which means that you get appropriate
visuals exposed in GL, along with many extensions under
direct-rendering that require presence in GLX (which aren't supported
in glxdriswrast.c).
v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
Drop triple-buffering, which was totally broken in practice (I'll
try to fix this later). Fix up some style nits. Document the
general flow of pageflipping and why, rename the DRI2 frame event
type enums to reflect what they're for, and handle them in a
single switch statement so you can understand the state machine
more easily.
v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
(not that the normal 2D driver is stable with pageflipping for
me), and I won't get it fixed before the merge window. It now
passes all of the OML_sync_control tests from Jamey and Theo
(except for occasional warns in timing -fullscreen -divisor 2).
v4: Fix doxygen at the top of vblank.c
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2013-12-31 02:23:38 +01:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Failed to initialize the DRI2 extension.\n");
|
|
|
|
}
|
2014-12-11 22:37:14 +01:00
|
|
|
|
2018-02-15 13:46:55 +01:00
|
|
|
if (!(ms->drmmode.present_enable = ms_present_screen_init(pScreen))) {
|
2014-12-11 22:37:14 +01:00
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
|
|
|
"Failed to initialize the Present extension.\n");
|
|
|
|
}
|
modesetting: Disable Reverse PRIME for i915
Reverse PRIME seems to be designed with discrete graphics as a sink in
mind, designed to do an extra copy from sysmem to vidmem to prevent a
discrete chip from needing to scan out from sysmem.
The criteria it used to detect this case is if we are a GPU screen and
Glamor accelerated. It's possible for i915 to fulfill these conditions,
despite the fact that the additional copy doesn't make sense for i915.
Normally, you could just set AccelMethod = none as an option for the device
and call it a day. However, when running with modesetting as both the sink
and the source, Glamor must be enabled.
Ideally, you would be able to set AccelMethod individually for devices
using the same driver, but there seems to be a bug in X option parsing that
makes all devices on a driver inherit the options from the first detected
device. Thus, glamor needs to be enabled for all or for none until that bug
(if it's even a bug) is fixed.
Nonetheless, it probably doesn't make sense to do the extra copy on i915
even if Glamor is enabled for the device, so this is more user friendly by
not requiring users to disable acceleration for i915.
v1: N/A
v2: N/A
v3: N/A
v4: Initial commit
v5: Unchanged
v6: Rebase onto ToT
v7: NULL check and free drmVersionPtr
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:55 +02:00
|
|
|
/* enable reverse prime if we are a GPU screen, and accelerated, and not
|
|
|
|
* i915. i915 is happy scanning out from sysmem. */
|
|
|
|
if (pScreen->isGPU) {
|
|
|
|
drmVersionPtr version;
|
|
|
|
|
|
|
|
/* enable if we are an accelerated GPU screen */
|
2015-06-10 05:41:02 +02:00
|
|
|
ms->drmmode.reverse_prime_offload_mode = TRUE;
|
modesetting: Disable Reverse PRIME for i915
Reverse PRIME seems to be designed with discrete graphics as a sink in
mind, designed to do an extra copy from sysmem to vidmem to prevent a
discrete chip from needing to scan out from sysmem.
The criteria it used to detect this case is if we are a GPU screen and
Glamor accelerated. It's possible for i915 to fulfill these conditions,
despite the fact that the additional copy doesn't make sense for i915.
Normally, you could just set AccelMethod = none as an option for the device
and call it a day. However, when running with modesetting as both the sink
and the source, Glamor must be enabled.
Ideally, you would be able to set AccelMethod individually for devices
using the same driver, but there seems to be a bug in X option parsing that
makes all devices on a driver inherit the options from the first detected
device. Thus, glamor needs to be enabled for all or for none until that bug
(if it's even a bug) is fixed.
Nonetheless, it probably doesn't make sense to do the extra copy on i915
even if Glamor is enabled for the device, so this is more user friendly by
not requiring users to disable acceleration for i915.
v1: N/A
v2: N/A
v3: N/A
v4: Initial commit
v5: Unchanged
v6: Rebase onto ToT
v7: NULL check and free drmVersionPtr
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
2016-06-17 05:06:55 +02:00
|
|
|
|
|
|
|
/* disable if we detect i915 */
|
|
|
|
if ((version = drmGetVersion(ms->drmmode.fd))) {
|
|
|
|
if (!strncmp("i915", version->name, version->name_len)) {
|
|
|
|
ms->drmmode.reverse_prime_offload_mode = FALSE;
|
|
|
|
}
|
|
|
|
drmFreeVersion(version);
|
|
|
|
}
|
|
|
|
}
|
modesetting: Add support for DRI2 with glamor.
This is derived from the intel driver DRI2 code, with swapchain and
pageflipping dropped, functions renamed, and vblank event management
shared code moved to a vblank.c for reuse by Present.
This allows AIGLX to load, which means that you get appropriate
visuals exposed in GL, along with many extensions under
direct-rendering that require presence in GLX (which aren't supported
in glxdriswrast.c).
v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
Drop triple-buffering, which was totally broken in practice (I'll
try to fix this later). Fix up some style nits. Document the
general flow of pageflipping and why, rename the DRI2 frame event
type enums to reflect what they're for, and handle them in a
single switch statement so you can understand the state machine
more easily.
v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
(not that the normal 2D driver is stable with pageflipping for
me), and I won't get it fixed before the merge window. It now
passes all of the OML_sync_control tests from Jamey and Theo
(except for occasional warns in timing -fullscreen -divisor 2).
v4: Fix doxygen at the top of vblank.c
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2013-12-31 02:23:38 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-05-02 22:54:57 +02:00
|
|
|
pScrn->vtSema = TRUE;
|
|
|
|
|
|
|
|
return TRUE;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-26 20:37:46 +02:00
|
|
|
AdjustFrame(ScrnInfoPtr pScrn, int x, int y)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2013-06-11 02:29:25 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
2008-05-28 16:55:36 +02:00
|
|
|
|
2013-06-11 02:29:25 +02:00
|
|
|
drmmode_adjust_frame(pScrn, &ms->drmmode, x, y);
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-26 20:37:46 +02:00
|
|
|
FreeScreen(ScrnInfoPtr pScrn)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2012-06-01 13:34:42 +02:00
|
|
|
FreeRec(pScrn);
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-26 20:37:46 +02:00
|
|
|
LeaveVT(ScrnInfoPtr pScrn)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2012-04-17 12:50:40 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
2014-10-08 09:39:15 +02:00
|
|
|
|
2012-04-17 12:48:03 +02:00
|
|
|
xf86_hide_cursors(pScrn);
|
|
|
|
|
2008-06-16 16:07:39 +02:00
|
|
|
pScrn->vtSema = FALSE;
|
2012-04-17 12:50:40 +02:00
|
|
|
|
2018-03-04 22:00:05 +01:00
|
|
|
#ifdef XF86_PDEV_SERVER_FD
|
2014-03-18 15:48:22 +01:00
|
|
|
if (ms->pEnt->location.type == BUS_PLATFORM &&
|
2014-10-08 09:39:15 +02:00
|
|
|
(ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
|
2014-03-18 15:48:22 +01:00
|
|
|
return;
|
2018-03-04 22:00:05 +01:00
|
|
|
#endif
|
2014-03-18 15:48:22 +01:00
|
|
|
|
2018-01-19 03:07:29 +01:00
|
|
|
if (!ms->fd_passed)
|
|
|
|
drmDropMaster(ms->fd);
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This gets called when gaining control of the VT, and from ScreenInit().
|
|
|
|
*/
|
|
|
|
static Bool
|
2014-08-26 20:37:46 +02:00
|
|
|
EnterVT(ScrnInfoPtr pScrn)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2011-09-29 15:05:43 +02:00
|
|
|
pScrn->vtSema = TRUE;
|
|
|
|
|
2014-03-18 15:48:22 +01:00
|
|
|
SetMaster(pScrn);
|
2012-04-17 12:50:40 +02:00
|
|
|
|
2016-05-02 22:54:57 +02:00
|
|
|
if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE))
|
2014-10-08 09:39:15 +02:00
|
|
|
return FALSE;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
return TRUE;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
2014-08-26 20:37:46 +02:00
|
|
|
SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
2014-08-26 20:37:46 +02:00
|
|
|
CloseScreen(ScreenPtr pScreen)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2012-06-01 13:34:42 +02:00
|
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
2008-05-28 16:55:36 +02:00
|
|
|
modesettingPtr ms = modesettingPTR(pScrn);
|
2015-07-22 04:56:13 +02:00
|
|
|
modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
|
|
|
|
|
|
|
|
/* Clear mask of assigned crtc's in this generation */
|
|
|
|
ms_ent->assigned_crtcs = 0;
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2017-05-16 20:37:14 +02:00
|
|
|
#ifdef GLAMOR_HAS_GBM
|
2018-02-15 13:46:55 +01:00
|
|
|
if (ms->drmmode.dri2_enable) {
|
modesetting: Add support for DRI2 with glamor.
This is derived from the intel driver DRI2 code, with swapchain and
pageflipping dropped, functions renamed, and vblank event management
shared code moved to a vblank.c for reuse by Present.
This allows AIGLX to load, which means that you get appropriate
visuals exposed in GL, along with many extensions under
direct-rendering that require presence in GLX (which aren't supported
in glxdriswrast.c).
v2: Drop unused header includes in pageflip.c, wrap in #ifdef GLAMOR.
Drop triple-buffering, which was totally broken in practice (I'll
try to fix this later). Fix up some style nits. Document the
general flow of pageflipping and why, rename the DRI2 frame event
type enums to reflect what they're for, and handle them in a
single switch statement so you can understand the state machine
more easily.
v3: Drop pageflipping entirely -- it's unstable on my Intel laptop
(not that the normal 2D driver is stable with pageflipping for
me), and I won't get it fixed before the merge window. It now
passes all of the OML_sync_control tests from Jamey and Theo
(except for occasional warns in timing -fullscreen -divisor 2).
v4: Fix doxygen at the top of vblank.c
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2013-12-31 02:23:38 +01:00
|
|
|
ms_dri2_close_screen(pScreen);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ms_vblank_close_screen(pScreen);
|
|
|
|
|
2011-09-29 13:38:26 +02:00
|
|
|
if (ms->damage) {
|
2014-10-08 09:39:15 +02:00
|
|
|
DamageUnregister(ms->damage);
|
|
|
|
DamageDestroy(ms->damage);
|
|
|
|
ms->damage = NULL;
|
2011-09-29 13:38:26 +02:00
|
|
|
}
|
|
|
|
|
2012-02-20 12:00:56 +01:00
|
|
|
if (ms->drmmode.shadow_enable) {
|
2019-10-08 18:52:28 +02:00
|
|
|
ms->shadow.Remove(pScreen, pScreen->GetScreenPixmap(pScreen));
|
2014-10-08 09:39:15 +02:00
|
|
|
free(ms->drmmode.shadow_fb);
|
|
|
|
ms->drmmode.shadow_fb = NULL;
|
2015-07-22 18:14:08 +02:00
|
|
|
free(ms->drmmode.shadow_fb2);
|
|
|
|
ms->drmmode.shadow_fb2 = NULL;
|
2011-09-29 16:55:36 +02:00
|
|
|
}
|
Add RandR leases with modesetting driver support [v6]
This adds support for RandR CRTC/Output leases through the modesetting
driver, creating a lease using new kernel infrastructure and returning
that to a client through an fd which will have access to only those
resources.
v2: Restore CRTC mode when leases terminate
When a lease terminates for a crtc we have saved data for, go
ahead and restore the saved mode.
v3: Report RR_Rotate_0 rotations for leased crtcs.
Ignore leased CRTCs when selecting screen size.
Stop leasing encoders, the kernel doesn't do that anymore.
Turn off crtc->enabled while leased so that modesetting
ignores them.
Check lease status before calling any driver mode functions
When starting a lease, mark leased CRTCs as disabled and hide
their cursors. Also, check to see if there are other
non-leased CRTCs which are driving leased Outputs and mark
them as disabled as well. Sometimes an application will lease
an idle crtc instead of the one already associated with the
leased output.
When terminating a lease, reset any CRTCs which are driving
outputs that are no longer leased so that they start working
again.
This required splitting the DIX level lease termination code
into two pieces, one to remove the lease from the system
(RRLeaseTerminated) and a new function that frees the lease
data structure (RRLeaseFree).
v4: Report RR_Rotate_0 rotation for leased crtcs.
v5: Terminate all leases on server reset.
Leases hang around after the associated client exits so that
the client doesn't need to occupy an X server client slot and
consume a file descriptor once it has gotten the output
resources necessary.
Any leases still hanging around when the X server resets or
shuts down need to be cleaned up by calling the kernel to
terminate the lease and freeing any DIX structures.
Note that we cannot simply use the existing
drmmode_terminate_lease function on each lease as that wants
to also reset the video mode, and during server shut down that
modesetting: Validate leases on VT enter
The kernel doesn't allow any master ioctls to run when another
VT is active, including simple things like listing the active
leases. To deal with that, we check the list of leases
whenever the X server VT is activated.
xfree86: hide disabled cursors when resetting after lease termination
The lessee may well have played with cursors and left one
active on our screen. Just tell the kernel to turn it off.
v6: Add meson build infrastructure
[Also bumped libdrm requirement - ajax]
Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2018-02-12 22:51:56 +01:00
|
|
|
|
2011-09-29 12:49:26 +02:00
|
|
|
drmmode_uevent_fini(pScrn, &ms->drmmode);
|
|
|
|
|
|
|
|
drmmode_free_bos(pScrn, &ms->drmmode);
|
|
|
|
|
2019-06-24 21:46:26 +02:00
|
|
|
if (ms->drmmode.pageflip) {
|
|
|
|
miPointerScreenPtr PointPriv =
|
|
|
|
dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
|
|
|
|
|
|
|
|
if (PointPriv->spriteFuncs == &drmmode_sprite_funcs)
|
|
|
|
PointPriv->spriteFuncs = ms->SpriteFuncs;
|
|
|
|
}
|
|
|
|
|
2008-06-16 16:07:39 +02:00
|
|
|
if (pScrn->vtSema) {
|
2014-08-26 20:37:46 +02:00
|
|
|
LeaveVT(pScrn);
|
2008-05-28 16:55:36 +02:00
|
|
|
}
|
2008-05-28 14:33:07 +02:00
|
|
|
|
2008-06-16 16:07:39 +02:00
|
|
|
pScreen->CreateScreenResources = ms->createScreenResources;
|
2011-09-29 13:38:26 +02:00
|
|
|
pScreen->BlockHandler = ms->BlockHandler;
|
2011-09-29 15:05:43 +02:00
|
|
|
|
2008-05-28 16:55:36 +02:00
|
|
|
pScrn->vtSema = FALSE;
|
|
|
|
pScreen->CloseScreen = ms->CloseScreen;
|
2014-08-26 20:37:46 +02:00
|
|
|
return (*pScreen->CloseScreen) (pScreen);
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static ModeStatus
|
2014-08-26 20:37:46 +02:00
|
|
|
ValidMode(ScrnInfoPtr arg, DisplayModePtr mode, Bool verbose, int flags)
|
2008-05-28 14:33:07 +02:00
|
|
|
{
|
2008-05-28 16:55:36 +02:00
|
|
|
return MODE_OK;
|
2008-05-28 14:33:07 +02:00
|
|
|
}
|