Home | History | Annotate | Line # | Download | only in modesetting
      1 /*
      2  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
      3  * Copyright 2011 Dave Airlie
      4  * Copyright 2019 NVIDIA CORPORATION
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sub license, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial portions
     17  * of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     22  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  *
     28  * Original Author: Alan Hourihane <alanh (at) tungstengraphics.com>
     29  * Rewrite: Dave Airlie <airlied (at) redhat.com>
     30  * Additional contributors:
     31  *   Aaron Plattner <aplattner (at) nvidia.com>
     32  *
     33  */
     34 
     35 #ifdef HAVE_DIX_CONFIG_H
     36 #include "dix-config.h"
     37 #endif
     38 
     39 #include <unistd.h>
     40 #include <fcntl.h>
     41 #include "xf86.h"
     42 #include "xf86Priv.h"
     43 #include "xf86_OSproc.h"
     44 #include "compiler.h"
     45 #include "xf86Pci.h"
     46 #include "mipointer.h"
     47 #include "mipointrst.h"
     48 #include "micmap.h"
     49 #include <X11/extensions/randr.h>
     50 #include "fb.h"
     51 #include "edid.h"
     52 #include "xf86i2c.h"
     53 #include "xf86Crtc.h"
     54 #include "miscstruct.h"
     55 #include "dixstruct.h"
     56 #include "xf86xv.h"
     57 #include <X11/extensions/Xv.h>
     58 #include <xorg-config.h>
     59 #ifdef XSERVER_PLATFORM_BUS
     60 #include "xf86platformBus.h"
     61 #endif
     62 #ifdef XSERVER_LIBPCIACCESS
     63 #include <pciaccess.h>
     64 #endif
     65 #include "driver.h"
     66 
     67 static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y);
     68 static Bool CloseScreen(ScreenPtr pScreen);
     69 static Bool EnterVT(ScrnInfoPtr pScrn);
     70 static void Identify(int flags);
     71 static const OptionInfoRec *AvailableOptions(int chipid, int busid);
     72 static ModeStatus ValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
     73                             Bool verbose, int flags);
     74 static void FreeScreen(ScrnInfoPtr pScrn);
     75 static void LeaveVT(ScrnInfoPtr pScrn);
     76 static Bool SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode);
     77 static Bool ScreenInit(ScreenPtr pScreen, int argc, char **argv);
     78 static Bool PreInit(ScrnInfoPtr pScrn, int flags);
     79 
     80 static Bool Probe(DriverPtr drv, int flags);
     81 static Bool ms_pci_probe(DriverPtr driver,
     82                          int entity_num, struct pci_device *device,
     83                          intptr_t match_data);
     84 static Bool ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data);
     85 
     86 /* window wrapper functions used to get the notification when
     87  * the window property changes */
     88 static Atom vrr_atom;
     89 static Bool property_vectors_wrapped;
     90 static Bool restore_property_vector;
     91 static int (*saved_change_property) (ClientPtr client);
     92 static int (*saved_delete_property) (ClientPtr client);
     93 
     94 #ifdef XSERVER_LIBPCIACCESS
     95 static const struct pci_id_match ms_device_match[] = {
     96     {
     97      PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
     98      0x00030000, 0x00ff0000, 0},
     99 
    100     {0, 0, 0},
    101 };
    102 #endif
    103 
    104 #ifndef XSERVER_PLATFORM_BUS
    105 struct xf86_platform_device;
    106 #endif
    107 
    108 #ifdef XSERVER_PLATFORM_BUS
    109 static Bool ms_platform_probe(DriverPtr driver,
    110                               int entity_num, int flags,
    111                               struct xf86_platform_device *device,
    112                               intptr_t match_data);
    113 #endif
    114 
    115 _X_EXPORT DriverRec modesetting = {
    116     1,
    117     "modesetting",
    118     Identify,
    119     Probe,
    120     AvailableOptions,
    121     NULL,
    122     0,
    123     ms_driver_func,
    124     ms_device_match,
    125     ms_pci_probe,
    126 #ifdef XSERVER_PLATFORM_BUS
    127     ms_platform_probe,
    128 #endif
    129 };
    130 
    131 static SymTabRec Chipsets[] = {
    132     {0, "kms"},
    133     {-1, NULL}
    134 };
    135 
    136 static const OptionInfoRec Options[] = {
    137     {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
    138     {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE},
    139     {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
    140     {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
    141     {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
    142     {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
    143     {OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE},
    144     {OPTION_ATOMIC, "Atomic", OPTV_BOOLEAN, {0}, FALSE},
    145     {OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE},
    146     {OPTION_USE_GAMMA_LUT, "UseGammaLUT", OPTV_BOOLEAN, {0}, FALSE},
    147     {OPTION_ASYNC_FLIP_SECONDARIES, "AsyncFlipSecondaries", OPTV_BOOLEAN, {0}, FALSE},
    148     {-1, NULL, OPTV_NONE, {0}, FALSE}
    149 };
    150 
    151 int ms_entity_index = -1;
    152 
    153 static MODULESETUPPROTO(Setup);
    154 
    155 static XF86ModuleVersionInfo VersRec = {
    156     "modesetting",
    157     MODULEVENDORSTRING,
    158     MODINFOSTRING1,
    159     MODINFOSTRING2,
    160     XORG_VERSION_CURRENT,
    161     XORG_VERSION_MAJOR,
    162     XORG_VERSION_MINOR,
    163     XORG_VERSION_PATCH,
    164     ABI_CLASS_VIDEODRV,
    165     ABI_VIDEODRV_VERSION,
    166     MOD_CLASS_VIDEODRV,
    167     {0, 0, 0, 0}
    168 };
    169 
    170 _X_EXPORT XF86ModuleData modesettingModuleData = { &VersRec, Setup, NULL };
    171 
    172 static void *
    173 Setup(void *module, void *opts, int *errmaj, int *errmin)
    174 {
    175     static Bool setupDone = 0;
    176 
    177     /* This module should be loaded only once, but check to be sure.
    178      */
    179     if (!setupDone) {
    180         setupDone = 1;
    181         xf86AddDriver(&modesetting, module, HaveDriverFuncs);
    182 
    183         /*
    184          * The return value must be non-NULL on success even though there
    185          * is no TearDownProc.
    186          */
    187         return (void *) 1;
    188     }
    189     else {
    190         if (errmaj)
    191             *errmaj = LDR_ONCEONLY;
    192         return NULL;
    193     }
    194 }
    195 
    196 static void
    197 Identify(int flags)
    198 {
    199     xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers",
    200                       Chipsets);
    201 }
    202 
    203 modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn)
    204 {
    205     DevUnion     *pPriv;
    206     modesettingPtr ms = modesettingPTR(scrn);
    207     pPriv = xf86GetEntityPrivate(ms->pEnt->index,
    208                                  ms_entity_index);
    209     return pPriv->ptr;
    210 }
    211 
    212 static int
    213 get_passed_fd(void)
    214 {
    215     if (xf86DRMMasterFd >= 0) {
    216         xf86DrvMsg(-1, X_INFO, "Using passed DRM master file descriptor %d\n", xf86DRMMasterFd);
    217         return dup(xf86DRMMasterFd);
    218     }
    219     return -1;
    220 }
    221 
    222 static int
    223 open_hw(const char *dev)
    224 {
    225     int fd;
    226 
    227     if ((fd = get_passed_fd()) != -1)
    228         return fd;
    229 
    230     if (dev)
    231         fd = open(dev, O_RDWR | O_CLOEXEC, 0);
    232     else {
    233         dev = getenv("KMSDEVICE");
    234         if ((NULL == dev) || ((fd = open(dev, O_RDWR | O_CLOEXEC, 0)) == -1)) {
    235             dev = "/dev/dri/card0";
    236             fd = open(dev, O_RDWR | O_CLOEXEC, 0);
    237         }
    238     }
    239     if (fd == -1)
    240         xf86DrvMsg(-1, X_ERROR, "open %s: %s\n", dev, strerror(errno));
    241 
    242     return fd;
    243 }
    244 
    245 static int
    246 check_outputs(int fd, int *count)
    247 {
    248     drmModeResPtr res = drmModeGetResources(fd);
    249     int ret;
    250 
    251     if (!res)
    252         return FALSE;
    253 
    254     if (count)
    255         *count = res->count_connectors;
    256 
    257     ret = res->count_connectors > 0;
    258 #if defined(GLAMOR_HAS_GBM_LINEAR)
    259     if (ret == FALSE) {
    260         uint64_t value = 0;
    261         if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0 &&
    262                 (value & DRM_PRIME_CAP_EXPORT))
    263             ret = TRUE;
    264     }
    265 #endif
    266     drmModeFreeResources(res);
    267     return ret;
    268 }
    269 
    270 static Bool
    271 probe_hw(const char *dev, struct xf86_platform_device *platform_dev)
    272 {
    273     int fd;
    274 
    275 #ifdef XF86_PDEV_SERVER_FD
    276     if (platform_dev && (platform_dev->flags & XF86_PDEV_SERVER_FD)) {
    277         fd = xf86_platform_device_odev_attributes(platform_dev)->fd;
    278         if (fd == -1)
    279             return FALSE;
    280         return check_outputs(fd, NULL);
    281     }
    282 #endif
    283 
    284     fd = open_hw(dev);
    285     if (fd != -1) {
    286         int ret = check_outputs(fd, NULL);
    287 
    288         close(fd);
    289         return ret;
    290     }
    291     return FALSE;
    292 }
    293 
    294 static char *
    295 ms_DRICreatePCIBusID(const struct pci_device *dev)
    296 {
    297     char *busID;
    298 
    299     if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
    300                  dev->domain, dev->bus, dev->dev, dev->func) == -1)
    301         return NULL;
    302 
    303     return busID;
    304 }
    305 
    306 static Bool
    307 probe_hw_pci(const char *dev, struct pci_device *pdev)
    308 {
    309     int ret = FALSE, fd = open_hw(dev);
    310     char *id, *devid;
    311     drmSetVersion sv;
    312 
    313     if (fd == -1)
    314         return FALSE;
    315 
    316     sv.drm_di_major = 1;
    317     sv.drm_di_minor = 4;
    318     sv.drm_dd_major = -1;
    319     sv.drm_dd_minor = -1;
    320     if (drmSetInterfaceVersion(fd, &sv)) {
    321         close(fd);
    322         return FALSE;
    323     }
    324 
    325     id = drmGetBusid(fd);
    326     devid = ms_DRICreatePCIBusID(pdev);
    327 
    328     if (id && devid && !strcmp(id, devid))
    329         ret = check_outputs(fd, NULL);
    330 
    331     close(fd);
    332     free(id);
    333     free(devid);
    334     return ret;
    335 }
    336 
    337 static const OptionInfoRec *
    338 AvailableOptions(int chipid, int busid)
    339 {
    340     return Options;
    341 }
    342 
    343 static Bool
    344 ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
    345 {
    346     xorgHWFlags *flag;
    347 
    348     switch (op) {
    349     case GET_REQUIRED_HW_INTERFACES:
    350         flag = (CARD32 *) data;
    351         (*flag) = 0;
    352         return TRUE;
    353     case SUPPORTS_SERVER_FDS:
    354         return TRUE;
    355     default:
    356         return FALSE;
    357     }
    358 }
    359 
    360 static void
    361 ms_setup_scrn_hooks(ScrnInfoPtr scrn)
    362 {
    363     scrn->driverVersion = 1;
    364     scrn->driverName = "modesetting";
    365     scrn->name = "modeset";
    366 
    367     scrn->Probe = NULL;
    368     scrn->PreInit = PreInit;
    369     scrn->ScreenInit = ScreenInit;
    370     scrn->SwitchMode = SwitchMode;
    371     scrn->AdjustFrame = AdjustFrame;
    372     scrn->EnterVT = EnterVT;
    373     scrn->LeaveVT = LeaveVT;
    374     scrn->FreeScreen = FreeScreen;
    375     scrn->ValidMode = ValidMode;
    376 }
    377 
    378 static void
    379 ms_setup_entity(ScrnInfoPtr scrn, int entity_num)
    380 {
    381     DevUnion *pPriv;
    382 
    383     xf86SetEntitySharable(entity_num);
    384 
    385     if (ms_entity_index == -1)
    386         ms_entity_index = xf86AllocateEntityPrivateIndex();
    387 
    388     pPriv = xf86GetEntityPrivate(entity_num,
    389                                  ms_entity_index);
    390 
    391     xf86SetEntityInstanceForScreen(scrn, entity_num, xf86GetNumEntityInstances(entity_num) - 1);
    392 
    393     if (!pPriv->ptr)
    394         pPriv->ptr = xnfcalloc(sizeof(modesettingEntRec), 1);
    395 }
    396 
    397 #ifdef XSERVER_LIBPCIACCESS
    398 static Bool
    399 ms_pci_probe(DriverPtr driver,
    400              int entity_num, struct pci_device *dev, intptr_t match_data)
    401 {
    402     ScrnInfoPtr scrn = NULL;
    403 
    404     scrn = xf86ConfigPciEntity(scrn, 0, entity_num, NULL,
    405                                NULL, NULL, NULL, NULL, NULL);
    406     if (scrn) {
    407         const char *devpath;
    408         GDevPtr devSection = xf86GetDevFromEntity(scrn->entityList[0],
    409                                                   scrn->entityInstanceList[0]);
    410 
    411         devpath = xf86FindOptionValue(devSection->options, "kmsdev");
    412         if (probe_hw_pci(devpath, dev)) {
    413             ms_setup_scrn_hooks(scrn);
    414 
    415             xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
    416                        "claimed PCI slot %d@%d:%d:%d\n",
    417                        dev->bus, dev->domain, dev->dev, dev->func);
    418             xf86DrvMsg(scrn->scrnIndex, X_INFO,
    419                        "using %s\n", devpath ? devpath : "default device");
    420 
    421             ms_setup_entity(scrn, entity_num);
    422         }
    423         else
    424             scrn = NULL;
    425     }
    426     return scrn != NULL;
    427 }
    428 #endif
    429 
    430 #ifdef XSERVER_PLATFORM_BUS
    431 static Bool
    432 ms_platform_probe(DriverPtr driver,
    433                   int entity_num, int flags, struct xf86_platform_device *dev,
    434                   intptr_t match_data)
    435 {
    436     ScrnInfoPtr scrn = NULL;
    437     const char *path = xf86_platform_device_odev_attributes(dev)->path;
    438     int scr_flags = 0;
    439 
    440     if (flags & PLATFORM_PROBE_GPU_SCREEN)
    441         scr_flags = XF86_ALLOCATE_GPU_SCREEN;
    442 
    443     if (probe_hw(path, dev)) {
    444         scrn = xf86AllocateScreen(driver, scr_flags);
    445         if (xf86IsEntitySharable(entity_num))
    446             xf86SetEntityShared(entity_num);
    447         xf86AddEntityToScreen(scrn, entity_num);
    448 
    449         ms_setup_scrn_hooks(scrn);
    450 
    451         xf86DrvMsg(scrn->scrnIndex, X_INFO,
    452                    "using drv %s\n", path ? path : "default device");
    453 
    454         ms_setup_entity(scrn, entity_num);
    455     }
    456 
    457     return scrn != NULL;
    458 }
    459 #endif
    460 
    461 static Bool
    462 Probe(DriverPtr drv, int flags)
    463 {
    464     int i, numDevSections;
    465     GDevPtr *devSections;
    466     Bool foundScreen = FALSE;
    467     const char *dev;
    468     ScrnInfoPtr scrn = NULL;
    469 
    470     /* For now, just bail out for PROBE_DETECT. */
    471     if (flags & PROBE_DETECT)
    472         return FALSE;
    473 
    474     /*
    475      * Find the config file Device sections that match this
    476      * driver, and return if there are none.
    477      */
    478     if ((numDevSections = xf86MatchDevice("modesetting", &devSections)) <= 0) {
    479         return FALSE;
    480     }
    481 
    482     for (i = 0; i < numDevSections; i++) {
    483         int entity_num;
    484         dev = xf86FindOptionValue(devSections[i]->options, "kmsdev");
    485         if (probe_hw(dev, NULL)) {
    486 
    487             entity_num = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
    488             scrn = xf86ConfigFbEntity(scrn, 0, entity_num, NULL, NULL, NULL, NULL);
    489         }
    490 
    491         if (scrn) {
    492             foundScreen = TRUE;
    493             ms_setup_scrn_hooks(scrn);
    494             scrn->Probe = Probe;
    495 
    496             xf86DrvMsg(scrn->scrnIndex, X_INFO,
    497                        "using %s\n", dev ? dev : "default device");
    498             ms_setup_entity(scrn, entity_num);
    499         }
    500     }
    501 
    502     free(devSections);
    503 
    504     return foundScreen;
    505 }
    506 
    507 static Bool
    508 GetRec(ScrnInfoPtr pScrn)
    509 {
    510     if (pScrn->driverPrivate)
    511         return TRUE;
    512 
    513     pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1);
    514 
    515     return TRUE;
    516 }
    517 
    518 static void
    519 rotate_clip(PixmapPtr pixmap, BoxPtr rect, drmModeClip *clip, Rotation rotation)
    520 {
    521     int w = pixmap->drawable.width;
    522     int h = pixmap->drawable.height;
    523 
    524     if (rotation == RR_Rotate_90) {
    525 	/* Rotate 90 degrees counter clockwise */
    526         clip->x1 = rect->y1;
    527 	clip->x2 = rect->y2;
    528 	clip->y1 = w - rect->x2;
    529 	clip->y2 = w - rect->x1;
    530     } else if (rotation == RR_Rotate_180) {
    531 	/* Rotate 180 degrees */
    532         clip->x1 = w - rect->x2;
    533 	clip->x2 = w - rect->x1;
    534 	clip->y1 = h - rect->y2;
    535 	clip->y2 = h - rect->y1;
    536     } else if (rotation == RR_Rotate_270) {
    537 	/* Rotate 90 degrees clockwise */
    538         clip->x1 = h - rect->y2;
    539 	clip->x2 = h - rect->y1;
    540 	clip->y1 = rect->x1;
    541 	clip->y2 = rect->x2;
    542     } else {
    543 	clip->x1 = rect->x1;
    544 	clip->x2 = rect->x2;
    545 	clip->y1 = rect->y1;
    546 	clip->y2 = rect->y2;
    547     }
    548 }
    549 
    550 static int
    551 dispatch_dirty_region(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
    552 		      PixmapPtr pixmap, DamagePtr damage, int fb_id)
    553 {
    554     modesettingPtr ms = modesettingPTR(scrn);
    555     RegionPtr dirty = DamageRegion(damage);
    556     unsigned num_cliprects = REGION_NUM_RECTS(dirty);
    557     int ret = 0;
    558 
    559     if (num_cliprects) {
    560         drmModeClip *clip = xallocarray(num_cliprects, sizeof(drmModeClip));
    561         BoxPtr rect = REGION_RECTS(dirty);
    562         int i;
    563 
    564         if (!clip)
    565             return -ENOMEM;
    566 
    567         /* Rotate and copy rects into clips */
    568         for (i = 0; i < num_cliprects; i++, rect++)
    569 	    rotate_clip(pixmap, rect, &clip[i], crtc->rotation);
    570 
    571         /* TODO query connector property to see if this is needed */
    572         ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects);
    573 
    574         /* if we're swamping it with work, try one at a time */
    575         if (ret == -EINVAL) {
    576             for (i = 0; i < num_cliprects; i++) {
    577                 if ((ret = drmModeDirtyFB(ms->fd, fb_id, &clip[i], 1)) < 0)
    578                     break;
    579             }
    580         }
    581 
    582         free(clip);
    583         DamageEmpty(damage);
    584     }
    585     return ret;
    586 }
    587 
    588 static void
    589 dispatch_dirty(ScreenPtr pScreen)
    590 {
    591     ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
    592     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    593     modesettingPtr ms = modesettingPTR(scrn);
    594     PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen);
    595     uint32_t fb_id;
    596     int ret, c, x, y ;
    597 
    598     for (c = 0; c < xf86_config->num_crtc; c++) {
    599         xf86CrtcPtr crtc = xf86_config->crtc[c];
    600         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
    601 
    602         if (!drmmode_crtc)
    603             continue;
    604 
    605 	drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y);
    606 
    607         ret = dispatch_dirty_region(scrn, crtc, pixmap, ms->damage, fb_id);
    608         if (ret == -EINVAL || ret == -ENOSYS) {
    609             ms->dirty_enabled = FALSE;
    610             DamageUnregister(ms->damage);
    611             DamageDestroy(ms->damage);
    612             ms->damage = NULL;
    613             xf86DrvMsg(scrn->scrnIndex, X_INFO,
    614                        "Disabling kernel dirty updates, not required.\n");
    615             return;
    616         }
    617     }
    618 }
    619 
    620 static void
    621 dispatch_dirty_pixmap(ScrnInfoPtr scrn, xf86CrtcPtr crtc, PixmapPtr ppix)
    622 {
    623     modesettingPtr ms = modesettingPTR(scrn);
    624     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
    625     DamagePtr damage = ppriv->secondary_damage;
    626     int fb_id = ppriv->fb_id;
    627 
    628     dispatch_dirty_region(scrn, crtc, ppix, damage, fb_id);
    629 }
    630 
    631 static void
    632 dispatch_secondary_dirty(ScreenPtr pScreen)
    633 {
    634     ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
    635     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    636     int c;
    637 
    638     for (c = 0; c < xf86_config->num_crtc; c++) {
    639         xf86CrtcPtr crtc = xf86_config->crtc[c];
    640         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
    641 
    642         if (!drmmode_crtc)
    643             continue;
    644 
    645         if (drmmode_crtc->prime_pixmap)
    646             dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap);
    647         if (drmmode_crtc->prime_pixmap_back)
    648             dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap_back);
    649     }
    650 }
    651 
    652 static void
    653 redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty, int *timeout)
    654 {
    655     RegionRec pixregion;
    656 
    657     PixmapRegionInit(&pixregion, dirty->secondary_dst);
    658     DamageRegionAppend(&dirty->secondary_dst->drawable, &pixregion);
    659     PixmapSyncDirtyHelper(dirty);
    660 
    661     if (!screen->isGPU) {
    662 #ifdef GLAMOR_HAS_GBM
    663         modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
    664         /*
    665          * When copying from the primary framebuffer to the shared pixmap,
    666          * we must ensure the copy is complete before the secondary starts a
    667          * copy to its own framebuffer (some secondarys scanout directly from
    668          * the shared pixmap, but not all).
    669          */
    670         if (ms->drmmode.glamor)
    671             ms->glamor.finish(screen);
    672 #endif
    673         /* Ensure the secondary processes the damage immediately */
    674         if (timeout)
    675             *timeout = 0;
    676     }
    677 
    678     DamageRegionProcessPending(&dirty->secondary_dst->drawable);
    679     RegionUninit(&pixregion);
    680 }
    681 
    682 static void
    683 ms_dirty_update(ScreenPtr screen, int *timeout)
    684 {
    685     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
    686 
    687     RegionPtr region;
    688     PixmapDirtyUpdatePtr ent;
    689 
    690     if (xorg_list_is_empty(&screen->pixmap_dirty_list))
    691         return;
    692 
    693     xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
    694         region = DamageRegion(ent->damage);
    695         if (RegionNotEmpty(region)) {
    696             if (!screen->isGPU) {
    697                    msPixmapPrivPtr ppriv =
    698                     msGetPixmapPriv(&ms->drmmode, ent->secondary_dst->primary_pixmap);
    699 
    700                 if (ppriv->notify_on_damage) {
    701                     ppriv->notify_on_damage = FALSE;
    702 
    703                     ent->secondary_dst->drawable.pScreen->
    704                         SharedPixmapNotifyDamage(ent->secondary_dst);
    705                 }
    706 
    707                 /* Requested manual updating */
    708                 if (ppriv->defer_dirty_update)
    709                     continue;
    710             }
    711 
    712             redisplay_dirty(screen, ent, timeout);
    713             DamageEmpty(ent->damage);
    714         }
    715     }
    716 }
    717 
    718 static PixmapDirtyUpdatePtr
    719 ms_dirty_get_ent(ScreenPtr screen, PixmapPtr secondary_dst)
    720 {
    721     PixmapDirtyUpdatePtr ent;
    722 
    723     if (xorg_list_is_empty(&screen->pixmap_dirty_list))
    724         return NULL;
    725 
    726     xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
    727         if (ent->secondary_dst == secondary_dst)
    728             return ent;
    729     }
    730 
    731     return NULL;
    732 }
    733 
    734 static void
    735 msBlockHandler(ScreenPtr pScreen, void *timeout)
    736 {
    737     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
    738 
    739     pScreen->BlockHandler = ms->BlockHandler;
    740     pScreen->BlockHandler(pScreen, timeout);
    741     ms->BlockHandler = pScreen->BlockHandler;
    742     pScreen->BlockHandler = msBlockHandler;
    743     if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode)
    744         dispatch_secondary_dirty(pScreen);
    745     else if (ms->dirty_enabled)
    746         dispatch_dirty(pScreen);
    747 
    748     ms_dirty_update(pScreen, timeout);
    749 }
    750 
    751 static void
    752 msBlockHandler_oneshot(ScreenPtr pScreen, void *pTimeout)
    753 {
    754     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    755     modesettingPtr ms = modesettingPTR(pScrn);
    756 
    757     msBlockHandler(pScreen, pTimeout);
    758 
    759     drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, FALSE);
    760 }
    761 
    762 Bool
    763 ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win) {
    764 	struct ms_vrr_priv *priv = dixLookupPrivate(&win->devPrivates, &ms->drmmode.vrrPrivateKeyRec);
    765 
    766 	return priv->variable_refresh;
    767 }
    768 
    769 static void
    770 ms_vrr_property_update(WindowPtr window, Bool variable_refresh)
    771 {
    772     ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen);
    773     modesettingPtr ms = modesettingPTR(scrn);
    774 
    775     struct ms_vrr_priv *priv = dixLookupPrivate(&window->devPrivates,
    776                                                 &ms->drmmode.vrrPrivateKeyRec);
    777     priv->variable_refresh = variable_refresh;
    778 
    779     if (ms->flip_window == window && ms->drmmode.present_flipping)
    780         ms_present_set_screen_vrr(scrn, variable_refresh);
    781 }
    782 
    783 /* Wrapper for xserver/dix/property.c:ProcChangeProperty */
    784 static int
    785 ms_change_property(ClientPtr client)
    786 {
    787     WindowPtr window = NULL;
    788     int ret = 0;
    789 
    790     REQUEST(xChangePropertyReq);
    791 
    792     client->requestVector[X_ChangeProperty] = saved_change_property;
    793     ret = saved_change_property(client);
    794 
    795     if (restore_property_vector)
    796         return ret;
    797 
    798     client->requestVector[X_ChangeProperty] = ms_change_property;
    799 
    800     if (ret != Success)
    801         return ret;
    802 
    803     ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
    804     if (ret != Success)
    805         return ret;
    806 
    807     // Checking for the VRR property change on the window
    808     if (stuff->property == vrr_atom &&
    809         xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit &&
    810         stuff->format == 32 && stuff->nUnits == 1) {
    811         uint32_t *value = (uint32_t *)(stuff + 1);
    812         ms_vrr_property_update(window, *value != 0);
    813     }
    814 
    815     return ret;
    816 }
    817 
    818 /* Wrapper for xserver/dix/property.c:ProcDeleteProperty */
    819 static int
    820 ms_delete_property(ClientPtr client)
    821 {
    822     WindowPtr window;
    823     int ret;
    824 
    825     REQUEST(xDeletePropertyReq);
    826 
    827     client->requestVector[X_DeleteProperty] = saved_delete_property;
    828     ret = saved_delete_property(client);
    829 
    830     if (restore_property_vector)
    831         return ret;
    832 
    833     client->requestVector[X_DeleteProperty] = ms_delete_property;
    834 
    835     if (ret != Success)
    836         return ret;
    837 
    838     ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
    839     if (ret != Success)
    840         return ret;
    841 
    842     if (stuff->property == vrr_atom &&
    843         xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit)
    844         ms_vrr_property_update(window, FALSE);
    845 
    846     return ret;
    847 }
    848 
    849 static void
    850 ms_unwrap_property_requests(ScrnInfoPtr scrn)
    851 {
    852     int i;
    853 
    854     if (!property_vectors_wrapped)
    855         return;
    856 
    857     if (ProcVector[X_ChangeProperty] == ms_change_property)
    858         ProcVector[X_ChangeProperty] = saved_change_property;
    859     else
    860         restore_property_vector = TRUE;
    861 
    862     if (ProcVector[X_DeleteProperty] == ms_delete_property)
    863         ProcVector[X_DeleteProperty] = saved_delete_property;
    864     else
    865         restore_property_vector = TRUE;
    866 
    867     for (i = 0; i < currentMaxClients; i++) {
    868         if (clients[i]->requestVector[X_ChangeProperty] == ms_change_property) {
    869             clients[i]->requestVector[X_ChangeProperty] = saved_change_property;
    870         } else {
    871             restore_property_vector = TRUE;
    872         }
    873 
    874         if (clients[i]->requestVector[X_DeleteProperty] == ms_delete_property) {
    875             clients[i]->requestVector[X_DeleteProperty] = saved_delete_property;
    876         } else {
    877             restore_property_vector = TRUE;
    878         }
    879     }
    880 
    881     if (restore_property_vector) {
    882         xf86DrvMsg(scrn->scrnIndex, X_WARNING,
    883                    "Couldn't unwrap some window property request vectors\n");
    884     }
    885 
    886     property_vectors_wrapped = FALSE;
    887 }
    888 
    889 static void
    890 FreeRec(ScrnInfoPtr pScrn)
    891 {
    892     modesettingPtr ms;
    893 
    894     if (!pScrn)
    895         return;
    896 
    897     ms = modesettingPTR(pScrn);
    898     if (!ms)
    899         return;
    900 
    901     if (ms->fd > 0) {
    902         modesettingEntPtr ms_ent;
    903         int ret;
    904 
    905         ms_ent = ms_ent_priv(pScrn);
    906         ms_ent->fd_ref--;
    907         if (!ms_ent->fd_ref) {
    908             ms_unwrap_property_requests(pScrn);
    909             if (ms->pEnt->location.type == BUS_PCI)
    910                 ret = drmClose(ms->fd);
    911             else
    912 #ifdef XF86_PDEV_SERVER_FD
    913                 if (!(ms->pEnt->location.type == BUS_PLATFORM &&
    914                       (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
    915 #endif
    916                     ret = close(ms->fd);
    917             (void) ret;
    918             ms_ent->fd = 0;
    919         }
    920     }
    921     pScrn->driverPrivate = NULL;
    922     free(ms->drmmode.Options);
    923     free(ms);
    924 
    925 }
    926 
    927 #ifdef GLAMOR_HAS_GBM
    928 
    929 static Bool
    930 load_glamor(ScrnInfoPtr pScrn)
    931 {
    932     void *mod = xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME);
    933     modesettingPtr ms = modesettingPTR(pScrn);
    934 
    935     if (!mod)
    936         return FALSE;
    937 
    938     ms->glamor.back_pixmap_from_fd = LoaderSymbolFromModule(mod, "glamor_back_pixmap_from_fd");
    939     ms->glamor.block_handler = LoaderSymbolFromModule(mod, "glamor_block_handler");
    940     ms->glamor.clear_pixmap = LoaderSymbolFromModule(mod, "glamor_clear_pixmap");
    941     ms->glamor.egl_create_textured_pixmap = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap");
    942     ms->glamor.egl_create_textured_pixmap_from_gbm_bo = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap_from_gbm_bo");
    943     ms->glamor.egl_exchange_buffers = LoaderSymbolFromModule(mod, "glamor_egl_exchange_buffers");
    944     ms->glamor.egl_get_gbm_device = LoaderSymbolFromModule(mod, "glamor_egl_get_gbm_device");
    945     ms->glamor.egl_init = LoaderSymbolFromModule(mod, "glamor_egl_init");
    946     ms->glamor.finish = LoaderSymbolFromModule(mod, "glamor_finish");
    947     ms->glamor.gbm_bo_from_pixmap = LoaderSymbolFromModule(mod, "glamor_gbm_bo_from_pixmap");
    948     ms->glamor.init = LoaderSymbolFromModule(mod, "glamor_init");
    949     ms->glamor.name_from_pixmap = LoaderSymbolFromModule(mod, "glamor_name_from_pixmap");
    950     ms->glamor.set_drawable_modifiers_func = LoaderSymbolFromModule(mod, "glamor_set_drawable_modifiers_func");
    951     ms->glamor.shareable_fd_from_pixmap = LoaderSymbolFromModule(mod, "glamor_shareable_fd_from_pixmap");
    952     ms->glamor.supports_pixmap_import_export = LoaderSymbolFromModule(mod, "glamor_supports_pixmap_import_export");
    953     ms->glamor.xv_init = LoaderSymbolFromModule(mod, "glamor_xv_init");
    954     ms->glamor.egl_get_driver_name = LoaderSymbolFromModule(mod, "glamor_egl_get_driver_name");
    955 
    956     return TRUE;
    957 }
    958 
    959 #endif
    960 
    961 static void
    962 try_enable_glamor(ScrnInfoPtr pScrn)
    963 {
    964     modesettingPtr ms = modesettingPTR(pScrn);
    965     const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options,
    966                                                        OPTION_ACCEL_METHOD);
    967     Bool do_glamor = (!accel_method_str ||
    968                       strcmp(accel_method_str, "glamor") == 0);
    969 
    970     ms->drmmode.glamor = FALSE;
    971 
    972 #ifdef GLAMOR_HAS_GBM
    973     if (ms->drmmode.force_24_32) {
    974         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cannot use glamor with 24bpp packed fb\n");
    975         return;
    976     }
    977 
    978     if (!do_glamor) {
    979         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n");
    980         return;
    981     }
    982 
    983     if (load_glamor(pScrn)) {
    984         if (ms->glamor.egl_init(pScrn, ms->fd)) {
    985             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n");
    986             ms->drmmode.glamor = TRUE;
    987         } else {
    988             xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    989                        "glamor initialization failed\n");
    990         }
    991     } else {
    992         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    993                    "Failed to load glamor module.\n");
    994     }
    995 #else
    996     if (do_glamor) {
    997         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    998                    "No glamor support in the X Server\n");
    999     }
   1000 #endif
   1001 }
   1002 
   1003 static Bool
   1004 msShouldDoubleShadow(ScrnInfoPtr pScrn, modesettingPtr ms)
   1005 {
   1006     Bool ret = FALSE, asked;
   1007     int from;
   1008     drmVersionPtr v = drmGetVersion(ms->fd);
   1009 
   1010     if (!ms->drmmode.shadow_enable)
   1011         return FALSE;
   1012 
   1013     if (!strcmp(v->name, "mgag200") ||
   1014         !strcmp(v->name, "ast")) /* XXX || rn50 */
   1015         ret = TRUE;
   1016 
   1017     drmFreeVersion(v);
   1018 
   1019     asked = xf86GetOptValBool(ms->drmmode.Options, OPTION_DOUBLE_SHADOW, &ret);
   1020 
   1021     if (asked)
   1022         from = X_CONFIG;
   1023     else
   1024         from = X_INFO;
   1025 
   1026     xf86DrvMsg(pScrn->scrnIndex, from,
   1027                "Double-buffered shadow updates: %s\n", ret ? "on" : "off");
   1028 
   1029     return ret;
   1030 }
   1031 
   1032 static Bool
   1033 ms_get_drm_master_fd(ScrnInfoPtr pScrn)
   1034 {
   1035     EntityInfoPtr pEnt;
   1036     modesettingPtr ms;
   1037     modesettingEntPtr ms_ent;
   1038 
   1039     ms = modesettingPTR(pScrn);
   1040     ms_ent = ms_ent_priv(pScrn);
   1041 
   1042     pEnt = ms->pEnt;
   1043 
   1044     if (ms_ent->fd) {
   1045         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1046                    " reusing fd for second head\n");
   1047         ms->fd = ms_ent->fd;
   1048         ms_ent->fd_ref++;
   1049         return TRUE;
   1050     }
   1051 
   1052     ms->fd_passed = FALSE;
   1053     if ((ms->fd = get_passed_fd()) >= 0) {
   1054         ms->fd_passed = TRUE;
   1055         return TRUE;
   1056     }
   1057 
   1058 #ifdef XSERVER_PLATFORM_BUS
   1059     if (pEnt->location.type == BUS_PLATFORM) {
   1060 #ifdef XF86_PDEV_SERVER_FD
   1061         if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)
   1062             ms->fd =
   1063                 xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
   1064                 fd;
   1065         else
   1066 #endif
   1067         {
   1068             char *path =
   1069                 xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
   1070                 path;
   1071             ms->fd = open_hw(path);
   1072         }
   1073     }
   1074     else
   1075 #endif
   1076 #ifdef XSERVER_LIBPCIACCESS
   1077     if (pEnt->location.type == BUS_PCI) {
   1078         char *BusID = NULL;
   1079         struct pci_device *PciInfo;
   1080 
   1081         PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
   1082         if (PciInfo) {
   1083             if ((BusID = ms_DRICreatePCIBusID(PciInfo)) != NULL) {
   1084                 ms->fd = drmOpen(NULL, BusID);
   1085                 free(BusID);
   1086             }
   1087         }
   1088     }
   1089     else
   1090 #endif
   1091     {
   1092         const char *devicename;
   1093         devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev");
   1094         ms->fd = open_hw(devicename);
   1095     }
   1096     if (ms->fd < 0)
   1097         return FALSE;
   1098 
   1099     ms_ent->fd = ms->fd;
   1100     ms_ent->fd_ref = 1;
   1101     return TRUE;
   1102 }
   1103 
   1104 static Bool
   1105 PreInit(ScrnInfoPtr pScrn, int flags)
   1106 {
   1107     modesettingPtr ms;
   1108     rgb defaultWeight = { 0, 0, 0 };
   1109     EntityInfoPtr pEnt;
   1110     uint64_t value = 0;
   1111     int ret;
   1112     int bppflags, connector_count;
   1113     int defaultdepth, defaultbpp;
   1114 
   1115     if (pScrn->numEntities != 1)
   1116         return FALSE;
   1117 
   1118     if (flags & PROBE_DETECT) {
   1119         return FALSE;
   1120     }
   1121 
   1122     /* Allocate driverPrivate */
   1123     if (!GetRec(pScrn))
   1124         return FALSE;
   1125 
   1126     pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
   1127 
   1128     ms = modesettingPTR(pScrn);
   1129     ms->SaveGeneration = -1;
   1130     ms->pEnt = pEnt;
   1131     ms->drmmode.is_secondary = FALSE;
   1132     pScrn->displayWidth = 640;  /* default it */
   1133 
   1134     if (xf86IsEntityShared(pScrn->entityList[0])) {
   1135         if (xf86IsPrimInitDone(pScrn->entityList[0]))
   1136             ms->drmmode.is_secondary = TRUE;
   1137         else
   1138             xf86SetPrimInitDone(pScrn->entityList[0]);
   1139     }
   1140 
   1141     pScrn->monitor = pScrn->confScreen->monitor;
   1142     pScrn->progClock = TRUE;
   1143     pScrn->rgbBits = 8;
   1144 
   1145     if (!ms_get_drm_master_fd(pScrn))
   1146         return FALSE;
   1147     ms->drmmode.fd = ms->fd;
   1148 
   1149     if (!check_outputs(ms->fd, &connector_count))
   1150         return FALSE;
   1151 
   1152     drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp);
   1153     if (defaultdepth == 24 && defaultbpp == 24) {
   1154         ms->drmmode.force_24_32 = TRUE;
   1155         ms->drmmode.kbpp = 24;
   1156         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1157                    "Using 24bpp hw front buffer with 32bpp shadow\n");
   1158         defaultbpp = 32;
   1159     } else {
   1160         ms->drmmode.kbpp = 0;
   1161     }
   1162     bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb;
   1163 
   1164     if (!xf86SetDepthBpp
   1165         (pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags))
   1166         return FALSE;
   1167 
   1168     switch (pScrn->depth) {
   1169     case 15:
   1170     case 16:
   1171     case 24:
   1172     case 30:
   1173         break;
   1174     default:
   1175         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1176                    "Given depth (%d) is not supported by the driver\n",
   1177                    pScrn->depth);
   1178         return FALSE;
   1179     }
   1180     xf86PrintDepthBpp(pScrn);
   1181     if (!ms->drmmode.kbpp)
   1182         ms->drmmode.kbpp = pScrn->bitsPerPixel;
   1183 
   1184     /* Process the options */
   1185     xf86CollectOptions(pScrn, NULL);
   1186     if (!(ms->drmmode.Options = malloc(sizeof(Options))))
   1187         return FALSE;
   1188     memcpy(ms->drmmode.Options, Options, sizeof(Options));
   1189     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options);
   1190 
   1191     if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
   1192         return FALSE;
   1193     if (!xf86SetDefaultVisual(pScrn, -1))
   1194         return FALSE;
   1195 
   1196     if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) {
   1197         ms->drmmode.sw_cursor = TRUE;
   1198     }
   1199 
   1200     ms->cursor_width = 64;
   1201     ms->cursor_height = 64;
   1202     ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value);
   1203     if (!ret) {
   1204         ms->cursor_width = value;
   1205     }
   1206     ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value);
   1207     if (!ret) {
   1208         ms->cursor_height = value;
   1209     }
   1210 
   1211     try_enable_glamor(pScrn);
   1212 
   1213     if (!ms->drmmode.glamor) {
   1214         Bool prefer_shadow = TRUE;
   1215 
   1216         if (ms->drmmode.force_24_32) {
   1217             prefer_shadow = TRUE;
   1218             ms->drmmode.shadow_enable = TRUE;
   1219         } else {
   1220             ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value);
   1221             if (!ret) {
   1222                 prefer_shadow = !!value;
   1223             }
   1224 
   1225             ms->drmmode.shadow_enable =
   1226                 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB,
   1227                                      prefer_shadow);
   1228         }
   1229 
   1230         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1231                    "ShadowFB: preferred %s, enabled %s\n",
   1232                    prefer_shadow ? "YES" : "NO",
   1233                    ms->drmmode.force_24_32 ? "FORCE" :
   1234                    ms->drmmode.shadow_enable ? "YES" : "NO");
   1235 
   1236         ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms);
   1237     } else {
   1238         if (!pScrn->is_gpu) {
   1239             MessageType from = xf86GetOptValBool(ms->drmmode.Options, OPTION_VARIABLE_REFRESH,
   1240                                                  &ms->vrr_support) ? X_CONFIG : X_DEFAULT;
   1241             xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n",
   1242                        ms->vrr_support ? "en" : "dis");
   1243 
   1244             ms->drmmode.async_flip_secondaries = FALSE;
   1245             from = xf86GetOptValBool(ms->drmmode.Options, OPTION_ASYNC_FLIP_SECONDARIES,
   1246                                      &ms->drmmode.async_flip_secondaries) ? X_CONFIG : X_DEFAULT;
   1247             xf86DrvMsg(pScrn->scrnIndex, from, "AsyncFlipSecondaries: %sabled\n",
   1248                        ms->drmmode.async_flip_secondaries ? "en" : "dis");
   1249         }
   1250     }
   1251 
   1252     ms->drmmode.pageflip =
   1253         xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE);
   1254 
   1255     pScrn->capabilities = 0;
   1256     ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value);
   1257     if (ret == 0) {
   1258         if (connector_count && (value & DRM_PRIME_CAP_IMPORT)) {
   1259             pScrn->capabilities |= RR_Capability_SinkOutput;
   1260             if (ms->drmmode.glamor)
   1261                 pScrn->capabilities |= RR_Capability_SinkOffload;
   1262         }
   1263 #ifdef GLAMOR_HAS_GBM_LINEAR
   1264         if (value & DRM_PRIME_CAP_EXPORT && ms->drmmode.glamor)
   1265             pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
   1266 #endif
   1267     }
   1268 
   1269     /*
   1270      * Use "atomic modesetting disable" request to detect if the kms driver is
   1271      * atomic capable, regardless if we will actually use atomic modesetting.
   1272      * This is effectively a no-op, we only care about the return status code.
   1273      */
   1274     ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 0);
   1275     ms->atomic_modeset_capable = (ret == 0);
   1276 
   1277     if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_ATOMIC, FALSE)) {
   1278         ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 1);
   1279         ms->atomic_modeset = (ret == 0);
   1280     } else {
   1281         ms->atomic_modeset = FALSE;
   1282     }
   1283 
   1284     ms->kms_has_modifiers = FALSE;
   1285     ret = drmGetCap(ms->fd, DRM_CAP_ADDFB2_MODIFIERS, &value);
   1286     if (ret == 0 && value != 0)
   1287         ms->kms_has_modifiers = TRUE;
   1288 
   1289     if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
   1290         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n");
   1291         goto fail;
   1292     }
   1293 
   1294     /*
   1295      * If the driver can do gamma correction, it should call xf86SetGamma() here.
   1296      */
   1297     {
   1298         Gamma zeros = { 0.0, 0.0, 0.0 };
   1299 
   1300         if (!xf86SetGamma(pScrn, zeros)) {
   1301             return FALSE;
   1302         }
   1303     }
   1304 
   1305     if (!(pScrn->is_gpu && connector_count == 0) && pScrn->modes == NULL) {
   1306         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
   1307         return FALSE;
   1308     }
   1309 
   1310     pScrn->currentMode = pScrn->modes;
   1311 
   1312     /* Set display resolution */
   1313     xf86SetDpi(pScrn, 0, 0);
   1314 
   1315     /* Load the required sub modules */
   1316     if (!xf86LoadSubModule(pScrn, "fb")) {
   1317         return FALSE;
   1318     }
   1319 
   1320     if (ms->drmmode.shadow_enable) {
   1321         void *mod = xf86LoadSubModule(pScrn, "shadow");
   1322 
   1323         if (!mod)
   1324             return FALSE;
   1325 
   1326         ms->shadow.Setup        = LoaderSymbolFromModule(mod, "shadowSetup");
   1327         ms->shadow.Add          = LoaderSymbolFromModule(mod, "shadowAdd");
   1328         ms->shadow.Remove       = LoaderSymbolFromModule(mod, "shadowRemove");
   1329         ms->shadow.Update32to24 = LoaderSymbolFromModule(mod, "shadowUpdate32to24");
   1330         ms->shadow.UpdatePacked = LoaderSymbolFromModule(mod, "shadowUpdatePacked");
   1331     }
   1332 
   1333     return TRUE;
   1334  fail:
   1335     return FALSE;
   1336 }
   1337 
   1338 static void *
   1339 msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
   1340                CARD32 *size, void *closure)
   1341 {
   1342     ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
   1343     modesettingPtr ms = modesettingPTR(pScrn);
   1344     int stride;
   1345 
   1346     stride = (pScrn->displayWidth * ms->drmmode.kbpp) / 8;
   1347     *size = stride;
   1348 
   1349     return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset);
   1350 }
   1351 
   1352 /* somewhat arbitrary tile size, in pixels */
   1353 #define TILE 16
   1354 
   1355 static int
   1356 msUpdateIntersect(modesettingPtr ms, shadowBufPtr pBuf, BoxPtr box,
   1357                   xRectangle *prect)
   1358 {
   1359     int i, dirty = 0, stride = pBuf->pPixmap->devKind, cpp = ms->drmmode.cpp;
   1360     int width = (box->x2 - box->x1) * cpp;
   1361     unsigned char *old, *new;
   1362 
   1363     old = ms->drmmode.shadow_fb2;
   1364     old += (box->y1 * stride) + (box->x1 * cpp);
   1365     new = ms->drmmode.shadow_fb;
   1366     new += (box->y1 * stride) + (box->x1 * cpp);
   1367 
   1368     for (i = box->y2 - box->y1 - 1; i >= 0; i--) {
   1369         unsigned char *o = old + i * stride,
   1370                       *n = new + i * stride;
   1371         if (memcmp(o, n, width) != 0) {
   1372             dirty = 1;
   1373             memcpy(o, n, width);
   1374         }
   1375     }
   1376 
   1377     if (dirty) {
   1378         prect->x = box->x1;
   1379         prect->y = box->y1;
   1380         prect->width = box->x2 - box->x1;
   1381         prect->height = box->y2 - box->y1;
   1382     }
   1383 
   1384     return dirty;
   1385 }
   1386 
   1387 static void
   1388 msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
   1389 {
   1390     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1391     modesettingPtr ms = modesettingPTR(pScrn);
   1392     Bool use_3224 = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32;
   1393 
   1394     if (ms->drmmode.shadow_enable2 && ms->drmmode.shadow_fb2) do {
   1395         RegionPtr damage = DamageRegion(pBuf->pDamage), tiles;
   1396         BoxPtr extents = RegionExtents(damage);
   1397         xRectangle *prect;
   1398         int nrects;
   1399         int i, j, tx1, tx2, ty1, ty2;
   1400 
   1401         tx1 = extents->x1 / TILE;
   1402         tx2 = (extents->x2 + TILE - 1) / TILE;
   1403         ty1 = extents->y1 / TILE;
   1404         ty2 = (extents->y2 + TILE - 1) / TILE;
   1405 
   1406         nrects = (tx2 - tx1) * (ty2 - ty1);
   1407         if (!(prect = calloc(nrects, sizeof(xRectangle))))
   1408             break;
   1409 
   1410         nrects = 0;
   1411         for (j = ty2 - 1; j >= ty1; j--) {
   1412             for (i = tx2 - 1; i >= tx1; i--) {
   1413                 BoxRec box;
   1414 
   1415                 box.x1 = max(i * TILE, extents->x1);
   1416                 box.y1 = max(j * TILE, extents->y1);
   1417                 box.x2 = min((i+1) * TILE, extents->x2);
   1418                 box.y2 = min((j+1) * TILE, extents->y2);
   1419 
   1420                 if (RegionContainsRect(damage, &box) != rgnOUT) {
   1421                     if (msUpdateIntersect(ms, pBuf, &box, prect + nrects)) {
   1422                         nrects++;
   1423                     }
   1424                 }
   1425             }
   1426         }
   1427 
   1428         tiles = RegionFromRects(nrects, prect, CT_NONE);
   1429         RegionIntersect(damage, damage, tiles);
   1430         RegionDestroy(tiles);
   1431         free(prect);
   1432     } while (0);
   1433 
   1434     if (use_3224)
   1435         ms->shadow.Update32to24(pScreen, pBuf);
   1436     else
   1437         ms->shadow.UpdatePacked(pScreen, pBuf);
   1438 }
   1439 
   1440 static Bool
   1441 msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back)
   1442 {
   1443     ScreenPtr screen = crtc->pScreen;
   1444     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1445     modesettingPtr ms = modesettingPTR(scrn);
   1446     EntityInfoPtr pEnt = ms->pEnt;
   1447     xf86CrtcPtr xf86Crtc = crtc->devPrivate;
   1448 
   1449     if (!xf86Crtc)
   1450         return FALSE;
   1451 
   1452     /* Not supported if we can't flip */
   1453     if (!ms->drmmode.pageflip)
   1454         return FALSE;
   1455 
   1456     /* Not currently supported with reverse PRIME */
   1457     if (ms->drmmode.reverse_prime_offload_mode)
   1458         return FALSE;
   1459 
   1460 #ifdef XSERVER_PLATFORM_BUS
   1461     if (pEnt->location.type == BUS_PLATFORM) {
   1462         char *syspath =
   1463             xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
   1464             syspath;
   1465 
   1466         /* Not supported for devices using USB transport due to misbehaved
   1467          * vblank events */
   1468         if (syspath && strstr(syspath, "usb"))
   1469             return FALSE;
   1470 
   1471         /* EVDI uses USB transport but is platform device, not usb.
   1472          * Exclude it explicitly. */
   1473         if (syspath && strstr(syspath, "evdi"))
   1474             return FALSE;
   1475     }
   1476 #endif
   1477 
   1478     return drmmode_EnableSharedPixmapFlipping(xf86Crtc, &ms->drmmode,
   1479                                               front, back);
   1480 }
   1481 
   1482 static void
   1483 msDisableSharedPixmapFlipping(RRCrtcPtr crtc)
   1484 {
   1485     ScreenPtr screen = crtc->pScreen;
   1486     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1487     modesettingPtr ms = modesettingPTR(scrn);
   1488     xf86CrtcPtr xf86Crtc = crtc->devPrivate;
   1489 
   1490     if (xf86Crtc)
   1491         drmmode_DisableSharedPixmapFlipping(xf86Crtc, &ms->drmmode);
   1492 }
   1493 
   1494 static Bool
   1495 msStartFlippingPixmapTracking(RRCrtcPtr crtc, DrawablePtr src,
   1496                               PixmapPtr secondary_dst1, PixmapPtr secondary_dst2,
   1497                               int x, int y, int dst_x, int dst_y,
   1498                               Rotation rotation)
   1499 {
   1500     ScreenPtr pScreen = src->pScreen;
   1501     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
   1502 
   1503     msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap),
   1504                     ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap);
   1505 
   1506     if (!PixmapStartDirtyTracking(src, secondary_dst1, x, y,
   1507                                   dst_x, dst_y, rotation)) {
   1508         return FALSE;
   1509     }
   1510 
   1511     if (!PixmapStartDirtyTracking(src, secondary_dst2, x, y,
   1512                                   dst_x, dst_y, rotation)) {
   1513         PixmapStopDirtyTracking(src, secondary_dst1);
   1514         return FALSE;
   1515     }
   1516 
   1517     ppriv1->secondary_src = src;
   1518     ppriv2->secondary_src = src;
   1519 
   1520     ppriv1->dirty = ms_dirty_get_ent(pScreen, secondary_dst1);
   1521     ppriv2->dirty = ms_dirty_get_ent(pScreen, secondary_dst2);
   1522 
   1523     ppriv1->defer_dirty_update = TRUE;
   1524     ppriv2->defer_dirty_update = TRUE;
   1525 
   1526     return TRUE;
   1527 }
   1528 
   1529 static Bool
   1530 msPresentSharedPixmap(PixmapPtr secondary_dst)
   1531 {
   1532     ScreenPtr pScreen = secondary_dst->primary_pixmap->drawable.pScreen;
   1533     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
   1534 
   1535     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, secondary_dst->primary_pixmap);
   1536 
   1537     RegionPtr region = DamageRegion(ppriv->dirty->damage);
   1538 
   1539     if (RegionNotEmpty(region)) {
   1540         redisplay_dirty(ppriv->secondary_src->pScreen, ppriv->dirty, NULL);
   1541         DamageEmpty(ppriv->dirty->damage);
   1542 
   1543         return TRUE;
   1544     }
   1545 
   1546     return FALSE;
   1547 }
   1548 
   1549 static Bool
   1550 msStopFlippingPixmapTracking(DrawablePtr src,
   1551                              PixmapPtr secondary_dst1, PixmapPtr secondary_dst2)
   1552 {
   1553     ScreenPtr pScreen = src->pScreen;
   1554     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
   1555 
   1556     msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap),
   1557                     ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap);
   1558 
   1559     Bool ret = TRUE;
   1560 
   1561     ret &= PixmapStopDirtyTracking(src, secondary_dst1);
   1562     ret &= PixmapStopDirtyTracking(src, secondary_dst2);
   1563 
   1564     if (ret) {
   1565         ppriv1->secondary_src = NULL;
   1566         ppriv2->secondary_src = NULL;
   1567 
   1568         ppriv1->dirty = NULL;
   1569         ppriv2->dirty = NULL;
   1570 
   1571         ppriv1->defer_dirty_update = FALSE;
   1572         ppriv2->defer_dirty_update = FALSE;
   1573     }
   1574 
   1575     return ret;
   1576 }
   1577 
   1578 static Bool
   1579 CreateScreenResources(ScreenPtr pScreen)
   1580 {
   1581     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1582     modesettingPtr ms = modesettingPTR(pScrn);
   1583     PixmapPtr rootPixmap;
   1584     Bool ret;
   1585     void *pixels = NULL;
   1586     int err;
   1587 
   1588     pScreen->CreateScreenResources = ms->createScreenResources;
   1589     ret = pScreen->CreateScreenResources(pScreen);
   1590     pScreen->CreateScreenResources = CreateScreenResources;
   1591 
   1592     if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, pScrn->is_gpu, FALSE))
   1593         return FALSE;
   1594 
   1595     if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode))
   1596         return FALSE;
   1597 
   1598     drmmode_uevent_init(pScrn, &ms->drmmode);
   1599 
   1600     if (!ms->drmmode.sw_cursor)
   1601         drmmode_map_cursor_bos(pScrn, &ms->drmmode);
   1602 
   1603     if (!ms->drmmode.gbm) {
   1604         pixels = drmmode_map_front_bo(&ms->drmmode);
   1605         if (!pixels)
   1606             return FALSE;
   1607     }
   1608 
   1609     rootPixmap = pScreen->GetScreenPixmap(pScreen);
   1610 
   1611     if (ms->drmmode.shadow_enable)
   1612         pixels = ms->drmmode.shadow_fb;
   1613 
   1614     if (ms->drmmode.shadow_enable2) {
   1615         ms->drmmode.shadow_fb2 = calloc(1, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3));
   1616         if (!ms->drmmode.shadow_fb2)
   1617             ms->drmmode.shadow_enable2 = FALSE;
   1618     }
   1619 
   1620     if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels))
   1621         FatalError("Couldn't adjust screen pixmap\n");
   1622 
   1623     if (ms->drmmode.shadow_enable) {
   1624         if (!ms->shadow.Add(pScreen, rootPixmap, msUpdatePacked, msShadowWindow,
   1625                             0, 0))
   1626             return FALSE;
   1627     }
   1628 
   1629     err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0);
   1630 
   1631     if (err != -EINVAL && err != -ENOSYS) {
   1632         ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
   1633                                   pScreen, rootPixmap);
   1634 
   1635         if (ms->damage) {
   1636             DamageRegister(&rootPixmap->drawable, ms->damage);
   1637             ms->dirty_enabled = TRUE;
   1638             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
   1639         }
   1640         else {
   1641             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1642                        "Failed to create screen damage record\n");
   1643             return FALSE;
   1644         }
   1645     }
   1646 
   1647     if (dixPrivateKeyRegistered(rrPrivKey)) {
   1648         rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
   1649 
   1650         pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping;
   1651         pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping;
   1652 
   1653         pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
   1654     }
   1655 
   1656     if (ms->vrr_support &&
   1657         !dixRegisterPrivateKey(&ms->drmmode.vrrPrivateKeyRec,
   1658                                PRIVATE_WINDOW,
   1659                                sizeof(struct ms_vrr_priv)))
   1660             return FALSE;
   1661 
   1662     return ret;
   1663 }
   1664 
   1665 static Bool
   1666 msSharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle)
   1667 {
   1668 #ifdef GLAMOR_HAS_GBM
   1669     modesettingPtr ms =
   1670         modesettingPTR(xf86ScreenToScrn(ppix->drawable.pScreen));
   1671     int ret;
   1672     CARD16 stride;
   1673     CARD32 size;
   1674     ret = ms->glamor.shareable_fd_from_pixmap(ppix->drawable.pScreen, ppix,
   1675                                               &stride, &size);
   1676     if (ret == -1)
   1677         return FALSE;
   1678 
   1679     *handle = (void *)(long)(ret);
   1680     return TRUE;
   1681 #endif
   1682     return FALSE;
   1683 }
   1684 
   1685 static Bool
   1686 msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
   1687 {
   1688 #ifdef GLAMOR_HAS_GBM
   1689     ScreenPtr screen = ppix->drawable.pScreen;
   1690     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1691     modesettingPtr ms = modesettingPTR(scrn);
   1692     Bool ret;
   1693     int ihandle = (int) (long) fd_handle;
   1694 
   1695     if (ihandle == -1)
   1696         if (!ms->drmmode.reverse_prime_offload_mode)
   1697            return drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, 0, 0);
   1698 
   1699     if (ms->drmmode.reverse_prime_offload_mode) {
   1700         ret = ms->glamor.back_pixmap_from_fd(ppix, ihandle,
   1701                                              ppix->drawable.width,
   1702                                              ppix->drawable.height,
   1703                                              ppix->devKind,
   1704                                              ppix->drawable.depth,
   1705                                              ppix->drawable.bitsPerPixel);
   1706     } else {
   1707         int size = ppix->devKind * ppix->drawable.height;
   1708         ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size);
   1709     }
   1710     if (ret == FALSE)
   1711         return ret;
   1712 
   1713     return TRUE;
   1714 #else
   1715     return FALSE;
   1716 #endif
   1717 }
   1718 
   1719 static Bool
   1720 msRequestSharedPixmapNotifyDamage(PixmapPtr ppix)
   1721 {
   1722     ScreenPtr screen = ppix->drawable.pScreen;
   1723     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1724     modesettingPtr ms = modesettingPTR(scrn);
   1725 
   1726     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix->primary_pixmap);
   1727 
   1728     ppriv->notify_on_damage = TRUE;
   1729 
   1730     return TRUE;
   1731 }
   1732 
   1733 static Bool
   1734 msSharedPixmapNotifyDamage(PixmapPtr ppix)
   1735 {
   1736     Bool ret = FALSE;
   1737     int c;
   1738 
   1739     ScreenPtr screen = ppix->drawable.pScreen;
   1740     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1741     modesettingPtr ms = modesettingPTR(scrn);
   1742     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
   1743 
   1744     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
   1745 
   1746     if (!ppriv->wait_for_damage)
   1747         return ret;
   1748     ppriv->wait_for_damage = FALSE;
   1749 
   1750     for (c = 0; c < xf86_config->num_crtc; c++) {
   1751         xf86CrtcPtr crtc = xf86_config->crtc[c];
   1752         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
   1753 
   1754         if (!drmmode_crtc)
   1755             continue;
   1756         if (!(drmmode_crtc->prime_pixmap && drmmode_crtc->prime_pixmap_back))
   1757             continue;
   1758 
   1759         // Received damage on primary screen pixmap, schedule present on vblank
   1760         ret |= drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, &ms->drmmode);
   1761     }
   1762 
   1763     return ret;
   1764 }
   1765 
   1766 static Bool
   1767 SetMaster(ScrnInfoPtr pScrn)
   1768 {
   1769     modesettingPtr ms = modesettingPTR(pScrn);
   1770     int ret;
   1771 
   1772 #ifdef XF86_PDEV_SERVER_FD
   1773     if (ms->pEnt->location.type == BUS_PLATFORM &&
   1774         (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
   1775         return TRUE;
   1776 #endif
   1777 
   1778     if (ms->fd_passed)
   1779         return TRUE;
   1780 
   1781     ret = drmSetMaster(ms->fd);
   1782     if (ret)
   1783         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n",
   1784                    strerror(errno));
   1785 
   1786     return ret == 0;
   1787 }
   1788 
   1789 /* When the root window is created, initialize the screen contents from
   1790  * console if -background none was specified on the command line
   1791  */
   1792 static Bool
   1793 CreateWindow_oneshot(WindowPtr pWin)
   1794 {
   1795     ScreenPtr pScreen = pWin->drawable.pScreen;
   1796     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1797     modesettingPtr ms = modesettingPTR(pScrn);
   1798     Bool ret;
   1799 
   1800     pScreen->CreateWindow = ms->CreateWindow;
   1801     ret = pScreen->CreateWindow(pWin);
   1802 
   1803     if (ret)
   1804         drmmode_copy_fb(pScrn, &ms->drmmode);
   1805     return ret;
   1806 }
   1807 
   1808 static Bool
   1809 ScreenInit(ScreenPtr pScreen, int argc, char **argv)
   1810 {
   1811     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1812     modesettingPtr ms = modesettingPTR(pScrn);
   1813     VisualPtr visual;
   1814 
   1815     pScrn->pScreen = pScreen;
   1816 
   1817     if (!SetMaster(pScrn))
   1818         return FALSE;
   1819 
   1820 #ifdef GLAMOR_HAS_GBM
   1821     if (ms->drmmode.glamor)
   1822         ms->drmmode.gbm = ms->glamor.egl_get_gbm_device(pScreen);
   1823 #endif
   1824 
   1825     /* HW dependent - FIXME */
   1826     pScrn->displayWidth = pScrn->virtualX;
   1827     if (!drmmode_create_initial_bos(pScrn, &ms->drmmode))
   1828         return FALSE;
   1829 
   1830     if (ms->drmmode.shadow_enable) {
   1831         ms->drmmode.shadow_fb =
   1832             calloc(1,
   1833                    pScrn->displayWidth * pScrn->virtualY *
   1834                    ((pScrn->bitsPerPixel + 7) >> 3));
   1835         if (!ms->drmmode.shadow_fb)
   1836             ms->drmmode.shadow_enable = FALSE;
   1837     }
   1838 
   1839     miClearVisualTypes();
   1840 
   1841     if (!miSetVisualTypes(pScrn->depth,
   1842                           miGetDefaultVisualMask(pScrn->depth),
   1843                           pScrn->rgbBits, pScrn->defaultVisual))
   1844         return FALSE;
   1845 
   1846     if (!miSetPixmapDepths())
   1847         return FALSE;
   1848 
   1849     if (!dixRegisterScreenSpecificPrivateKey
   1850         (pScreen, &ms->drmmode.pixmapPrivateKeyRec, PRIVATE_PIXMAP,
   1851          sizeof(msPixmapPrivRec))) {
   1852         return FALSE;
   1853     }
   1854 
   1855     pScrn->memPhysBase = 0;
   1856     pScrn->fbOffset = 0;
   1857 
   1858     if (!fbScreenInit(pScreen, NULL,
   1859                       pScrn->virtualX, pScrn->virtualY,
   1860                       pScrn->xDpi, pScrn->yDpi,
   1861                       pScrn->displayWidth, pScrn->bitsPerPixel))
   1862         return FALSE;
   1863 
   1864     if (pScrn->bitsPerPixel > 8) {
   1865         /* Fixup RGB ordering */
   1866         visual = pScreen->visuals + pScreen->numVisuals;
   1867         while (--visual >= pScreen->visuals) {
   1868             if ((visual->class | DynamicClass) == DirectColor) {
   1869                 visual->offsetRed = pScrn->offset.red;
   1870                 visual->offsetGreen = pScrn->offset.green;
   1871                 visual->offsetBlue = pScrn->offset.blue;
   1872                 visual->redMask = pScrn->mask.red;
   1873                 visual->greenMask = pScrn->mask.green;
   1874                 visual->blueMask = pScrn->mask.blue;
   1875             }
   1876         }
   1877     }
   1878 
   1879     fbPictureInit(pScreen, NULL, 0);
   1880 
   1881     if (drmmode_init(pScrn, &ms->drmmode) == FALSE) {
   1882         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1883                    "Failed to initialize glamor at ScreenInit() time.\n");
   1884         return FALSE;
   1885     }
   1886 
   1887     if (ms->drmmode.shadow_enable && !ms->shadow.Setup(pScreen)) {
   1888         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "shadow fb init failed\n");
   1889         return FALSE;
   1890     }
   1891 
   1892     ms->createScreenResources = pScreen->CreateScreenResources;
   1893     pScreen->CreateScreenResources = CreateScreenResources;
   1894 
   1895     xf86SetBlackWhitePixels(pScreen);
   1896 
   1897     xf86SetBackingStore(pScreen);
   1898     xf86SetSilkenMouse(pScreen);
   1899     miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
   1900 
   1901     /* If pageflip is enabled hook the screen's cursor-sprite (swcursor) funcs.
   1902      * So that we can disable page-flipping on fallback to a swcursor. */
   1903     if (ms->drmmode.pageflip) {
   1904         miPointerScreenPtr PointPriv =
   1905             dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
   1906 
   1907         if (!dixRegisterScreenPrivateKey(&ms->drmmode.spritePrivateKeyRec,
   1908                                          pScreen, PRIVATE_DEVICE,
   1909                                          sizeof(msSpritePrivRec)))
   1910             return FALSE;
   1911 
   1912         ms->SpriteFuncs = PointPriv->spriteFuncs;
   1913         PointPriv->spriteFuncs = &drmmode_sprite_funcs;
   1914     }
   1915 
   1916     /* Need to extend HWcursor support to handle mask interleave */
   1917     if (!ms->drmmode.sw_cursor)
   1918         xf86_cursors_init(pScreen, ms->cursor_width, ms->cursor_height,
   1919                           HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
   1920                           HARDWARE_CURSOR_UPDATE_UNHIDDEN |
   1921                           HARDWARE_CURSOR_ARGB);
   1922 
   1923     /* Must force it before EnterVT, so we are in control of VT and
   1924      * later memory should be bound when allocating, e.g rotate_mem */
   1925     pScrn->vtSema = TRUE;
   1926 
   1927     if (serverGeneration == 1 && bgNoneRoot && ms->drmmode.glamor) {
   1928         ms->CreateWindow = pScreen->CreateWindow;
   1929         pScreen->CreateWindow = CreateWindow_oneshot;
   1930     }
   1931 
   1932     pScreen->SaveScreen = xf86SaveScreen;
   1933     ms->CloseScreen = pScreen->CloseScreen;
   1934     pScreen->CloseScreen = CloseScreen;
   1935 
   1936     ms->BlockHandler = pScreen->BlockHandler;
   1937     pScreen->BlockHandler = msBlockHandler_oneshot;
   1938 
   1939     pScreen->SharePixmapBacking = msSharePixmapBacking;
   1940     pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking;
   1941     pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
   1942     pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
   1943 
   1944     pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage;
   1945     pScreen->RequestSharedPixmapNotifyDamage =
   1946         msRequestSharedPixmapNotifyDamage;
   1947 
   1948     pScreen->PresentSharedPixmap = msPresentSharedPixmap;
   1949     pScreen->StopFlippingPixmapTracking = msStopFlippingPixmapTracking;
   1950 
   1951     if (!xf86CrtcScreenInit(pScreen))
   1952         return FALSE;
   1953 
   1954     if (!drmmode_setup_colormap(pScreen, pScrn))
   1955         return FALSE;
   1956 
   1957     if (ms->atomic_modeset)
   1958         xf86DPMSInit(pScreen, drmmode_set_dpms, 0);
   1959     else
   1960         xf86DPMSInit(pScreen, xf86DPMSSet, 0);
   1961 
   1962 #ifdef GLAMOR_HAS_GBM
   1963     if (ms->drmmode.glamor) {
   1964         XF86VideoAdaptorPtr     glamor_adaptor;
   1965 
   1966         glamor_adaptor = ms->glamor.xv_init(pScreen, 16);
   1967         if (glamor_adaptor != NULL)
   1968             xf86XVScreenInit(pScreen, &glamor_adaptor, 1);
   1969         else
   1970             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1971                        "Failed to initialize XV support.\n");
   1972     }
   1973 #endif
   1974 
   1975     if (serverGeneration == 1)
   1976         xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
   1977 
   1978     if (!ms_vblank_screen_init(pScreen)) {
   1979         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1980                    "Failed to initialize vblank support.\n");
   1981         return FALSE;
   1982     }
   1983 
   1984 #ifdef GLAMOR_HAS_GBM
   1985     if (ms->drmmode.glamor) {
   1986         if (!(ms->drmmode.dri2_enable = ms_dri2_screen_init(pScreen))) {
   1987             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1988                        "Failed to initialize the DRI2 extension.\n");
   1989         }
   1990 
   1991         /* enable reverse prime if we are a GPU screen, and accelerated, and not
   1992          * i915, evdi or udl. i915 is happy scanning out from sysmem.
   1993          * evdi and udl are virtual drivers scanning out from sysmem
   1994          * backed dumb buffers.
   1995          */
   1996         if (pScreen->isGPU) {
   1997             drmVersionPtr version;
   1998 
   1999             /* enable if we are an accelerated GPU screen */
   2000             ms->drmmode.reverse_prime_offload_mode = TRUE;
   2001 
   2002             if ((version = drmGetVersion(ms->drmmode.fd))) {
   2003                 if (!strncmp("i915", version->name, version->name_len)) {
   2004                     ms->drmmode.reverse_prime_offload_mode = FALSE;
   2005                 }
   2006                 if (!strncmp("evdi", version->name, version->name_len)) {
   2007                     ms->drmmode.reverse_prime_offload_mode = FALSE;
   2008                 }
   2009                 if (!strncmp("udl", version->name, version->name_len)) {
   2010                     ms->drmmode.reverse_prime_offload_mode = FALSE;
   2011                 }
   2012                 if (!ms->drmmode.reverse_prime_offload_mode) {
   2013                     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   2014                        "Disable reverse prime offload mode for %s.\n", version->name);
   2015                 }
   2016                 drmFreeVersion(version);
   2017             }
   2018         }
   2019     }
   2020 #endif
   2021     if (!(ms->drmmode.present_enable = ms_present_screen_init(pScreen))) {
   2022         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   2023                    "Failed to initialize the Present extension.\n");
   2024     }
   2025 
   2026 
   2027     pScrn->vtSema = TRUE;
   2028 
   2029     if (ms->vrr_support) {
   2030         if (!property_vectors_wrapped) {
   2031             saved_change_property = ProcVector[X_ChangeProperty];
   2032             ProcVector[X_ChangeProperty] = ms_change_property;
   2033             saved_delete_property = ProcVector[X_DeleteProperty];
   2034             ProcVector[X_DeleteProperty] = ms_delete_property;
   2035             property_vectors_wrapped = TRUE;
   2036         }
   2037         vrr_atom = MakeAtom("_VARIABLE_REFRESH",
   2038                              strlen("_VARIABLE_REFRESH"), TRUE);
   2039     }
   2040 
   2041     return TRUE;
   2042 }
   2043 
   2044 static void
   2045 AdjustFrame(ScrnInfoPtr pScrn, int x, int y)
   2046 {
   2047     modesettingPtr ms = modesettingPTR(pScrn);
   2048 
   2049     drmmode_adjust_frame(pScrn, &ms->drmmode, x, y);
   2050 }
   2051 
   2052 static void
   2053 FreeScreen(ScrnInfoPtr pScrn)
   2054 {
   2055     FreeRec(pScrn);
   2056 }
   2057 
   2058 static void
   2059 LeaveVT(ScrnInfoPtr pScrn)
   2060 {
   2061     modesettingPtr ms = modesettingPTR(pScrn);
   2062 
   2063     xf86_hide_cursors(pScrn);
   2064 
   2065     pScrn->vtSema = FALSE;
   2066 
   2067 #ifdef XF86_PDEV_SERVER_FD
   2068     if (ms->pEnt->location.type == BUS_PLATFORM &&
   2069         (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
   2070         return;
   2071 #endif
   2072 
   2073     if (!ms->fd_passed)
   2074         drmDropMaster(ms->fd);
   2075 }
   2076 
   2077 /*
   2078  * This gets called when gaining control of the VT, and from ScreenInit().
   2079  */
   2080 static Bool
   2081 EnterVT(ScrnInfoPtr pScrn)
   2082 {
   2083     modesettingPtr ms = modesettingPTR(pScrn);
   2084 
   2085     pScrn->vtSema = TRUE;
   2086 
   2087     SetMaster(pScrn);
   2088 
   2089     drmmode_update_kms_state(&ms->drmmode);
   2090 
   2091     /* allow not all modes to be set successfully since some events might have
   2092      * happened while not being master that could prevent the previous
   2093      * configuration from being re-applied.
   2094      */
   2095     if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, TRUE)) {
   2096         xf86DisableUnusedFunctions(pScrn);
   2097 
   2098         /* TODO: check that at least one screen is on, to allow the user to fix
   2099          * their setup if all modeset failed...
   2100          */
   2101 
   2102         /* Tell the desktop environment that something changed, so that they
   2103          * can hopefully correct the situation
   2104          */
   2105         RRSetChanged(xf86ScrnToScreen(pScrn));
   2106         RRTellChanged(xf86ScrnToScreen(pScrn));
   2107     }
   2108 
   2109     return TRUE;
   2110 }
   2111 
   2112 static Bool
   2113 SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
   2114 {
   2115     return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
   2116 }
   2117 
   2118 static Bool
   2119 CloseScreen(ScreenPtr pScreen)
   2120 {
   2121     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   2122     modesettingPtr ms = modesettingPTR(pScrn);
   2123     modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
   2124 
   2125     /* Clear mask of assigned crtc's in this generation */
   2126     ms_ent->assigned_crtcs = 0;
   2127 
   2128 #ifdef GLAMOR_HAS_GBM
   2129     if (ms->drmmode.dri2_enable) {
   2130         ms_dri2_close_screen(pScreen);
   2131     }
   2132 #endif
   2133 
   2134     ms_vblank_close_screen(pScreen);
   2135 
   2136     if (ms->damage) {
   2137         DamageUnregister(ms->damage);
   2138         DamageDestroy(ms->damage);
   2139         ms->damage = NULL;
   2140     }
   2141 
   2142     if (ms->drmmode.shadow_enable) {
   2143         ms->shadow.Remove(pScreen, pScreen->GetScreenPixmap(pScreen));
   2144         free(ms->drmmode.shadow_fb);
   2145         ms->drmmode.shadow_fb = NULL;
   2146         free(ms->drmmode.shadow_fb2);
   2147         ms->drmmode.shadow_fb2 = NULL;
   2148     }
   2149 
   2150     drmmode_uevent_fini(pScrn, &ms->drmmode);
   2151 
   2152     drmmode_free_bos(pScrn, &ms->drmmode);
   2153 
   2154     if (ms->drmmode.pageflip) {
   2155         miPointerScreenPtr PointPriv =
   2156             dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
   2157 
   2158         if (PointPriv->spriteFuncs == &drmmode_sprite_funcs)
   2159             PointPriv->spriteFuncs = ms->SpriteFuncs;
   2160     }
   2161 
   2162     if (pScrn->vtSema) {
   2163         LeaveVT(pScrn);
   2164     }
   2165 
   2166     pScreen->CreateScreenResources = ms->createScreenResources;
   2167     pScreen->BlockHandler = ms->BlockHandler;
   2168 
   2169     pScrn->vtSema = FALSE;
   2170     pScreen->CloseScreen = ms->CloseScreen;
   2171     return (*pScreen->CloseScreen) (pScreen);
   2172 }
   2173 
   2174 static ModeStatus
   2175 ValidMode(ScrnInfoPtr arg, DisplayModePtr mode, Bool verbose, int flags)
   2176 {
   2177     return MODE_OK;
   2178 }
   2179