xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

driver.c (62763B)


      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@tungstengraphics.com>
     29  * Rewrite: Dave Airlie <airlied@redhat.com>
     30  * Additional contributors:
     31  *   Aaron Plattner <aplattner@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 int
    519 dispatch_dirty_region(ScrnInfoPtr scrn,
    520                       PixmapPtr pixmap, DamagePtr damage, int fb_id)
    521 {
    522     modesettingPtr ms = modesettingPTR(scrn);
    523     RegionPtr dirty = DamageRegion(damage);
    524     unsigned num_cliprects = REGION_NUM_RECTS(dirty);
    525     int ret = 0;
    526 
    527     if (num_cliprects) {
    528         drmModeClip *clip = xallocarray(num_cliprects, sizeof(drmModeClip));
    529         BoxPtr rect = REGION_RECTS(dirty);
    530         int i;
    531 
    532         if (!clip)
    533             return -ENOMEM;
    534 
    535         /* XXX no need for copy? */
    536         for (i = 0; i < num_cliprects; i++, rect++) {
    537             clip[i].x1 = rect->x1;
    538             clip[i].y1 = rect->y1;
    539             clip[i].x2 = rect->x2;
    540             clip[i].y2 = rect->y2;
    541         }
    542 
    543         /* TODO query connector property to see if this is needed */
    544         ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects);
    545 
    546         /* if we're swamping it with work, try one at a time */
    547         if (ret == -EINVAL) {
    548             for (i = 0; i < num_cliprects; i++) {
    549                 if ((ret = drmModeDirtyFB(ms->fd, fb_id, &clip[i], 1)) < 0)
    550                     break;
    551             }
    552         }
    553 
    554         free(clip);
    555         DamageEmpty(damage);
    556     }
    557     return ret;
    558 }
    559 
    560 static void
    561 dispatch_dirty(ScreenPtr pScreen)
    562 {
    563     ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
    564     modesettingPtr ms = modesettingPTR(scrn);
    565     PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen);
    566     int fb_id = ms->drmmode.fb_id;
    567     int ret;
    568 
    569     ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id);
    570     if (ret == -EINVAL || ret == -ENOSYS) {
    571         ms->dirty_enabled = FALSE;
    572         DamageUnregister(ms->damage);
    573         DamageDestroy(ms->damage);
    574         ms->damage = NULL;
    575         xf86DrvMsg(scrn->scrnIndex, X_INFO,
    576                    "Disabling kernel dirty updates, not required.\n");
    577         return;
    578     }
    579 }
    580 
    581 static void
    582 dispatch_dirty_pixmap(ScrnInfoPtr scrn, xf86CrtcPtr crtc, PixmapPtr ppix)
    583 {
    584     modesettingPtr ms = modesettingPTR(scrn);
    585     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
    586     DamagePtr damage = ppriv->secondary_damage;
    587     int fb_id = ppriv->fb_id;
    588 
    589     dispatch_dirty_region(scrn, ppix, damage, fb_id);
    590 }
    591 
    592 static void
    593 dispatch_secondary_dirty(ScreenPtr pScreen)
    594 {
    595     ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
    596     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    597     int c;
    598 
    599     for (c = 0; c < xf86_config->num_crtc; c++) {
    600         xf86CrtcPtr crtc = xf86_config->crtc[c];
    601         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
    602 
    603         if (!drmmode_crtc)
    604             continue;
    605 
    606         if (drmmode_crtc->prime_pixmap)
    607             dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap);
    608         if (drmmode_crtc->prime_pixmap_back)
    609             dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap_back);
    610     }
    611 }
    612 
    613 static void
    614 redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty, int *timeout)
    615 {
    616     RegionRec pixregion;
    617 
    618     PixmapRegionInit(&pixregion, dirty->secondary_dst);
    619     DamageRegionAppend(&dirty->secondary_dst->drawable, &pixregion);
    620     PixmapSyncDirtyHelper(dirty);
    621 
    622     if (!screen->isGPU) {
    623 #ifdef GLAMOR_HAS_GBM
    624         modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
    625         /*
    626          * When copying from the primary framebuffer to the shared pixmap,
    627          * we must ensure the copy is complete before the secondary starts a
    628          * copy to its own framebuffer (some secondarys scanout directly from
    629          * the shared pixmap, but not all).
    630          */
    631         if (ms->drmmode.glamor)
    632             ms->glamor.finish(screen);
    633 #endif
    634         /* Ensure the secondary processes the damage immediately */
    635         if (timeout)
    636             *timeout = 0;
    637     }
    638 
    639     DamageRegionProcessPending(&dirty->secondary_dst->drawable);
    640     RegionUninit(&pixregion);
    641 }
    642 
    643 static void
    644 ms_dirty_update(ScreenPtr screen, int *timeout)
    645 {
    646     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
    647 
    648     RegionPtr region;
    649     PixmapDirtyUpdatePtr ent;
    650 
    651     if (xorg_list_is_empty(&screen->pixmap_dirty_list))
    652         return;
    653 
    654     xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
    655         region = DamageRegion(ent->damage);
    656         if (RegionNotEmpty(region)) {
    657             if (!screen->isGPU) {
    658                    msPixmapPrivPtr ppriv =
    659                     msGetPixmapPriv(&ms->drmmode, ent->secondary_dst->primary_pixmap);
    660 
    661                 if (ppriv->notify_on_damage) {
    662                     ppriv->notify_on_damage = FALSE;
    663 
    664                     ent->secondary_dst->drawable.pScreen->
    665                         SharedPixmapNotifyDamage(ent->secondary_dst);
    666                 }
    667 
    668                 /* Requested manual updating */
    669                 if (ppriv->defer_dirty_update)
    670                     continue;
    671             }
    672 
    673             redisplay_dirty(screen, ent, timeout);
    674             DamageEmpty(ent->damage);
    675         }
    676     }
    677 }
    678 
    679 static PixmapDirtyUpdatePtr
    680 ms_dirty_get_ent(ScreenPtr screen, PixmapPtr secondary_dst)
    681 {
    682     PixmapDirtyUpdatePtr ent;
    683 
    684     if (xorg_list_is_empty(&screen->pixmap_dirty_list))
    685         return NULL;
    686 
    687     xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
    688         if (ent->secondary_dst == secondary_dst)
    689             return ent;
    690     }
    691 
    692     return NULL;
    693 }
    694 
    695 static void
    696 msBlockHandler(ScreenPtr pScreen, void *timeout)
    697 {
    698     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
    699 
    700     pScreen->BlockHandler = ms->BlockHandler;
    701     pScreen->BlockHandler(pScreen, timeout);
    702     ms->BlockHandler = pScreen->BlockHandler;
    703     pScreen->BlockHandler = msBlockHandler;
    704     if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode)
    705         dispatch_secondary_dirty(pScreen);
    706     else if (ms->dirty_enabled)
    707         dispatch_dirty(pScreen);
    708 
    709     ms_dirty_update(pScreen, timeout);
    710 }
    711 
    712 static void
    713 msBlockHandler_oneshot(ScreenPtr pScreen, void *pTimeout)
    714 {
    715     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    716     modesettingPtr ms = modesettingPTR(pScrn);
    717 
    718     msBlockHandler(pScreen, pTimeout);
    719 
    720     drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, FALSE);
    721 }
    722 
    723 Bool
    724 ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win) {
    725 	struct ms_vrr_priv *priv = dixLookupPrivate(&win->devPrivates, &ms->drmmode.vrrPrivateKeyRec);
    726 
    727 	return priv->variable_refresh;
    728 }
    729 
    730 static void
    731 ms_vrr_property_update(WindowPtr window, Bool variable_refresh)
    732 {
    733     ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen);
    734     modesettingPtr ms = modesettingPTR(scrn);
    735 
    736     struct ms_vrr_priv *priv = dixLookupPrivate(&window->devPrivates,
    737                                                 &ms->drmmode.vrrPrivateKeyRec);
    738     priv->variable_refresh = variable_refresh;
    739 
    740     if (ms->flip_window == window && ms->drmmode.present_flipping)
    741         ms_present_set_screen_vrr(scrn, variable_refresh);
    742 }
    743 
    744 /* Wrapper for xserver/dix/property.c:ProcChangeProperty */
    745 static int
    746 ms_change_property(ClientPtr client)
    747 {
    748     WindowPtr window = NULL;
    749     int ret = 0;
    750 
    751     REQUEST(xChangePropertyReq);
    752 
    753     client->requestVector[X_ChangeProperty] = saved_change_property;
    754     ret = saved_change_property(client);
    755 
    756     if (restore_property_vector)
    757         return ret;
    758 
    759     client->requestVector[X_ChangeProperty] = ms_change_property;
    760 
    761     if (ret != Success)
    762         return ret;
    763 
    764     ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
    765     if (ret != Success)
    766         return ret;
    767 
    768     // Checking for the VRR property change on the window
    769     if (stuff->property == vrr_atom &&
    770         xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit &&
    771         stuff->format == 32 && stuff->nUnits == 1) {
    772         uint32_t *value = (uint32_t *)(stuff + 1);
    773         ms_vrr_property_update(window, *value != 0);
    774     }
    775 
    776     return ret;
    777 }
    778 
    779 /* Wrapper for xserver/dix/property.c:ProcDeleteProperty */
    780 static int
    781 ms_delete_property(ClientPtr client)
    782 {
    783     WindowPtr window;
    784     int ret;
    785 
    786     REQUEST(xDeletePropertyReq);
    787 
    788     client->requestVector[X_DeleteProperty] = saved_delete_property;
    789     ret = saved_delete_property(client);
    790 
    791     if (restore_property_vector)
    792         return ret;
    793 
    794     client->requestVector[X_DeleteProperty] = ms_delete_property;
    795 
    796     if (ret != Success)
    797         return ret;
    798 
    799     ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
    800     if (ret != Success)
    801         return ret;
    802 
    803     if (stuff->property == vrr_atom &&
    804         xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit)
    805         ms_vrr_property_update(window, FALSE);
    806 
    807     return ret;
    808 }
    809 
    810 static void
    811 ms_unwrap_property_requests(ScrnInfoPtr scrn)
    812 {
    813     int i;
    814 
    815     if (!property_vectors_wrapped)
    816         return;
    817 
    818     if (ProcVector[X_ChangeProperty] == ms_change_property)
    819         ProcVector[X_ChangeProperty] = saved_change_property;
    820     else
    821         restore_property_vector = TRUE;
    822 
    823     if (ProcVector[X_DeleteProperty] == ms_delete_property)
    824         ProcVector[X_DeleteProperty] = saved_delete_property;
    825     else
    826         restore_property_vector = TRUE;
    827 
    828     for (i = 0; i < currentMaxClients; i++) {
    829         if (clients[i]->requestVector[X_ChangeProperty] == ms_change_property) {
    830             clients[i]->requestVector[X_ChangeProperty] = saved_change_property;
    831         } else {
    832             restore_property_vector = TRUE;
    833         }
    834 
    835         if (clients[i]->requestVector[X_DeleteProperty] == ms_delete_property) {
    836             clients[i]->requestVector[X_DeleteProperty] = saved_delete_property;
    837         } else {
    838             restore_property_vector = TRUE;
    839         }
    840     }
    841 
    842     if (restore_property_vector) {
    843         xf86DrvMsg(scrn->scrnIndex, X_WARNING,
    844                    "Couldn't unwrap some window property request vectors\n");
    845     }
    846 
    847     property_vectors_wrapped = FALSE;
    848 }
    849 
    850 static void
    851 FreeRec(ScrnInfoPtr pScrn)
    852 {
    853     modesettingPtr ms;
    854 
    855     if (!pScrn)
    856         return;
    857 
    858     ms = modesettingPTR(pScrn);
    859     if (!ms)
    860         return;
    861 
    862     if (ms->fd > 0) {
    863         modesettingEntPtr ms_ent;
    864         int ret;
    865 
    866         ms_ent = ms_ent_priv(pScrn);
    867         ms_ent->fd_ref--;
    868         if (!ms_ent->fd_ref) {
    869             ms_unwrap_property_requests(pScrn);
    870             if (ms->pEnt->location.type == BUS_PCI)
    871                 ret = drmClose(ms->fd);
    872             else
    873 #ifdef XF86_PDEV_SERVER_FD
    874                 if (!(ms->pEnt->location.type == BUS_PLATFORM &&
    875                       (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
    876 #endif
    877                     ret = close(ms->fd);
    878             (void) ret;
    879             ms_ent->fd = 0;
    880         }
    881     }
    882     pScrn->driverPrivate = NULL;
    883     free(ms->drmmode.Options);
    884     free(ms);
    885 
    886 }
    887 
    888 #ifdef GLAMOR_HAS_GBM
    889 
    890 static Bool
    891 load_glamor(ScrnInfoPtr pScrn)
    892 {
    893     void *mod = xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME);
    894     modesettingPtr ms = modesettingPTR(pScrn);
    895 
    896     if (!mod)
    897         return FALSE;
    898 
    899     ms->glamor.back_pixmap_from_fd = LoaderSymbolFromModule(mod, "glamor_back_pixmap_from_fd");
    900     ms->glamor.block_handler = LoaderSymbolFromModule(mod, "glamor_block_handler");
    901     ms->glamor.clear_pixmap = LoaderSymbolFromModule(mod, "glamor_clear_pixmap");
    902     ms->glamor.egl_create_textured_pixmap = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap");
    903     ms->glamor.egl_create_textured_pixmap_from_gbm_bo = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap_from_gbm_bo");
    904     ms->glamor.egl_exchange_buffers = LoaderSymbolFromModule(mod, "glamor_egl_exchange_buffers");
    905     ms->glamor.egl_get_gbm_device = LoaderSymbolFromModule(mod, "glamor_egl_get_gbm_device");
    906     ms->glamor.egl_init = LoaderSymbolFromModule(mod, "glamor_egl_init");
    907     ms->glamor.finish = LoaderSymbolFromModule(mod, "glamor_finish");
    908     ms->glamor.gbm_bo_from_pixmap = LoaderSymbolFromModule(mod, "glamor_gbm_bo_from_pixmap");
    909     ms->glamor.init = LoaderSymbolFromModule(mod, "glamor_init");
    910     ms->glamor.name_from_pixmap = LoaderSymbolFromModule(mod, "glamor_name_from_pixmap");
    911     ms->glamor.set_drawable_modifiers_func = LoaderSymbolFromModule(mod, "glamor_set_drawable_modifiers_func");
    912     ms->glamor.shareable_fd_from_pixmap = LoaderSymbolFromModule(mod, "glamor_shareable_fd_from_pixmap");
    913     ms->glamor.supports_pixmap_import_export = LoaderSymbolFromModule(mod, "glamor_supports_pixmap_import_export");
    914     ms->glamor.xv_init = LoaderSymbolFromModule(mod, "glamor_xv_init");
    915     ms->glamor.egl_get_driver_name = LoaderSymbolFromModule(mod, "glamor_egl_get_driver_name");
    916 
    917     return TRUE;
    918 }
    919 
    920 #endif
    921 
    922 static void
    923 try_enable_glamor(ScrnInfoPtr pScrn)
    924 {
    925     modesettingPtr ms = modesettingPTR(pScrn);
    926     const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options,
    927                                                        OPTION_ACCEL_METHOD);
    928     Bool do_glamor = (!accel_method_str ||
    929                       strcmp(accel_method_str, "glamor") == 0);
    930 
    931     ms->drmmode.glamor = FALSE;
    932 
    933 #ifdef GLAMOR_HAS_GBM
    934     if (ms->drmmode.force_24_32) {
    935         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cannot use glamor with 24bpp packed fb\n");
    936         return;
    937     }
    938 
    939     if (!do_glamor) {
    940         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n");
    941         return;
    942     }
    943 
    944     if (load_glamor(pScrn)) {
    945         if (ms->glamor.egl_init(pScrn, ms->fd)) {
    946             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n");
    947             ms->drmmode.glamor = TRUE;
    948         } else {
    949             xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    950                        "glamor initialization failed\n");
    951         }
    952     } else {
    953         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    954                    "Failed to load glamor module.\n");
    955     }
    956 #else
    957     if (do_glamor) {
    958         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    959                    "No glamor support in the X Server\n");
    960     }
    961 #endif
    962 }
    963 
    964 static Bool
    965 msShouldDoubleShadow(ScrnInfoPtr pScrn, modesettingPtr ms)
    966 {
    967     Bool ret = FALSE, asked;
    968     int from;
    969     drmVersionPtr v = drmGetVersion(ms->fd);
    970 
    971     if (!ms->drmmode.shadow_enable)
    972         return FALSE;
    973 
    974     if (!strcmp(v->name, "mgag200") ||
    975         !strcmp(v->name, "ast")) /* XXX || rn50 */
    976         ret = TRUE;
    977 
    978     drmFreeVersion(v);
    979 
    980     asked = xf86GetOptValBool(ms->drmmode.Options, OPTION_DOUBLE_SHADOW, &ret);
    981 
    982     if (asked)
    983         from = X_CONFIG;
    984     else
    985         from = X_INFO;
    986 
    987     xf86DrvMsg(pScrn->scrnIndex, from,
    988                "Double-buffered shadow updates: %s\n", ret ? "on" : "off");
    989 
    990     return ret;
    991 }
    992 
    993 static Bool
    994 ms_get_drm_master_fd(ScrnInfoPtr pScrn)
    995 {
    996     EntityInfoPtr pEnt;
    997     modesettingPtr ms;
    998     modesettingEntPtr ms_ent;
    999 
   1000     ms = modesettingPTR(pScrn);
   1001     ms_ent = ms_ent_priv(pScrn);
   1002 
   1003     pEnt = ms->pEnt;
   1004 
   1005     if (ms_ent->fd) {
   1006         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1007                    " reusing fd for second head\n");
   1008         ms->fd = ms_ent->fd;
   1009         ms_ent->fd_ref++;
   1010         return TRUE;
   1011     }
   1012 
   1013     ms->fd_passed = FALSE;
   1014     if ((ms->fd = get_passed_fd()) >= 0) {
   1015         ms->fd_passed = TRUE;
   1016         return TRUE;
   1017     }
   1018 
   1019 #ifdef XSERVER_PLATFORM_BUS
   1020     if (pEnt->location.type == BUS_PLATFORM) {
   1021 #ifdef XF86_PDEV_SERVER_FD
   1022         if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)
   1023             ms->fd =
   1024                 xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
   1025                 fd;
   1026         else
   1027 #endif
   1028         {
   1029             char *path =
   1030                 xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
   1031                 path;
   1032             ms->fd = open_hw(path);
   1033         }
   1034     }
   1035     else
   1036 #endif
   1037 #ifdef XSERVER_LIBPCIACCESS
   1038     if (pEnt->location.type == BUS_PCI) {
   1039         char *BusID = NULL;
   1040         struct pci_device *PciInfo;
   1041 
   1042         PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
   1043         if (PciInfo) {
   1044             if ((BusID = ms_DRICreatePCIBusID(PciInfo)) != NULL) {
   1045                 ms->fd = drmOpen(NULL, BusID);
   1046                 free(BusID);
   1047             }
   1048         }
   1049     }
   1050     else
   1051 #endif
   1052     {
   1053         const char *devicename;
   1054         devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev");
   1055         ms->fd = open_hw(devicename);
   1056     }
   1057     if (ms->fd < 0)
   1058         return FALSE;
   1059 
   1060     ms_ent->fd = ms->fd;
   1061     ms_ent->fd_ref = 1;
   1062     return TRUE;
   1063 }
   1064 
   1065 static Bool
   1066 PreInit(ScrnInfoPtr pScrn, int flags)
   1067 {
   1068     modesettingPtr ms;
   1069     rgb defaultWeight = { 0, 0, 0 };
   1070     EntityInfoPtr pEnt;
   1071     uint64_t value = 0;
   1072     int ret;
   1073     int bppflags, connector_count;
   1074     int defaultdepth, defaultbpp;
   1075 
   1076     if (pScrn->numEntities != 1)
   1077         return FALSE;
   1078 
   1079     if (flags & PROBE_DETECT) {
   1080         return FALSE;
   1081     }
   1082 
   1083     /* Allocate driverPrivate */
   1084     if (!GetRec(pScrn))
   1085         return FALSE;
   1086 
   1087     pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
   1088 
   1089     ms = modesettingPTR(pScrn);
   1090     ms->SaveGeneration = -1;
   1091     ms->pEnt = pEnt;
   1092     ms->drmmode.is_secondary = FALSE;
   1093     pScrn->displayWidth = 640;  /* default it */
   1094 
   1095     if (xf86IsEntityShared(pScrn->entityList[0])) {
   1096         if (xf86IsPrimInitDone(pScrn->entityList[0]))
   1097             ms->drmmode.is_secondary = TRUE;
   1098         else
   1099             xf86SetPrimInitDone(pScrn->entityList[0]);
   1100     }
   1101 
   1102     pScrn->monitor = pScrn->confScreen->monitor;
   1103     pScrn->progClock = TRUE;
   1104     pScrn->rgbBits = 8;
   1105 
   1106     if (!ms_get_drm_master_fd(pScrn))
   1107         return FALSE;
   1108     ms->drmmode.fd = ms->fd;
   1109 
   1110     if (!check_outputs(ms->fd, &connector_count))
   1111         return FALSE;
   1112 
   1113     drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp);
   1114     if (defaultdepth == 24 && defaultbpp == 24) {
   1115         ms->drmmode.force_24_32 = TRUE;
   1116         ms->drmmode.kbpp = 24;
   1117         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1118                    "Using 24bpp hw front buffer with 32bpp shadow\n");
   1119         defaultbpp = 32;
   1120     } else {
   1121         ms->drmmode.kbpp = 0;
   1122     }
   1123     bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb;
   1124 
   1125     if (!xf86SetDepthBpp
   1126         (pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags))
   1127         return FALSE;
   1128 
   1129     switch (pScrn->depth) {
   1130     case 15:
   1131     case 16:
   1132     case 24:
   1133     case 30:
   1134         break;
   1135     default:
   1136         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1137                    "Given depth (%d) is not supported by the driver\n",
   1138                    pScrn->depth);
   1139         return FALSE;
   1140     }
   1141     xf86PrintDepthBpp(pScrn);
   1142     if (!ms->drmmode.kbpp)
   1143         ms->drmmode.kbpp = pScrn->bitsPerPixel;
   1144 
   1145     /* Process the options */
   1146     xf86CollectOptions(pScrn, NULL);
   1147     if (!(ms->drmmode.Options = malloc(sizeof(Options))))
   1148         return FALSE;
   1149     memcpy(ms->drmmode.Options, Options, sizeof(Options));
   1150     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options);
   1151 
   1152     if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
   1153         return FALSE;
   1154     if (!xf86SetDefaultVisual(pScrn, -1))
   1155         return FALSE;
   1156 
   1157     if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) {
   1158         ms->drmmode.sw_cursor = TRUE;
   1159     }
   1160 
   1161     ms->cursor_width = 64;
   1162     ms->cursor_height = 64;
   1163     ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value);
   1164     if (!ret) {
   1165         ms->cursor_width = value;
   1166     }
   1167     ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value);
   1168     if (!ret) {
   1169         ms->cursor_height = value;
   1170     }
   1171 
   1172     try_enable_glamor(pScrn);
   1173 
   1174     if (!ms->drmmode.glamor) {
   1175         Bool prefer_shadow = TRUE;
   1176 
   1177         if (ms->drmmode.force_24_32) {
   1178             prefer_shadow = TRUE;
   1179             ms->drmmode.shadow_enable = TRUE;
   1180         } else {
   1181             ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value);
   1182             if (!ret) {
   1183                 prefer_shadow = !!value;
   1184             }
   1185 
   1186             ms->drmmode.shadow_enable =
   1187                 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB,
   1188                                      prefer_shadow);
   1189         }
   1190 
   1191         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1192                    "ShadowFB: preferred %s, enabled %s\n",
   1193                    prefer_shadow ? "YES" : "NO",
   1194                    ms->drmmode.force_24_32 ? "FORCE" :
   1195                    ms->drmmode.shadow_enable ? "YES" : "NO");
   1196 
   1197         ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms);
   1198     } else {
   1199         if (!pScrn->is_gpu) {
   1200             MessageType from = xf86GetOptValBool(ms->drmmode.Options, OPTION_VARIABLE_REFRESH,
   1201                                                  &ms->vrr_support) ? X_CONFIG : X_DEFAULT;
   1202             xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n",
   1203                        ms->vrr_support ? "en" : "dis");
   1204 
   1205             ms->drmmode.async_flip_secondaries = FALSE;
   1206             from = xf86GetOptValBool(ms->drmmode.Options, OPTION_ASYNC_FLIP_SECONDARIES,
   1207                                      &ms->drmmode.async_flip_secondaries) ? X_CONFIG : X_DEFAULT;
   1208             xf86DrvMsg(pScrn->scrnIndex, from, "AsyncFlipSecondaries: %sabled\n",
   1209                        ms->drmmode.async_flip_secondaries ? "en" : "dis");
   1210         }
   1211     }
   1212 
   1213     ms->drmmode.pageflip =
   1214         xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE);
   1215 
   1216     pScrn->capabilities = 0;
   1217     ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value);
   1218     if (ret == 0) {
   1219         if (connector_count && (value & DRM_PRIME_CAP_IMPORT)) {
   1220             pScrn->capabilities |= RR_Capability_SinkOutput;
   1221             if (ms->drmmode.glamor)
   1222                 pScrn->capabilities |= RR_Capability_SinkOffload;
   1223         }
   1224 #ifdef GLAMOR_HAS_GBM_LINEAR
   1225         if (value & DRM_PRIME_CAP_EXPORT && ms->drmmode.glamor)
   1226             pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
   1227 #endif
   1228     }
   1229 
   1230     /*
   1231      * Use "atomic modesetting disable" request to detect if the kms driver is
   1232      * atomic capable, regardless if we will actually use atomic modesetting.
   1233      * This is effectively a no-op, we only care about the return status code.
   1234      */
   1235     ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 0);
   1236     ms->atomic_modeset_capable = (ret == 0);
   1237 
   1238     if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_ATOMIC, FALSE)) {
   1239         ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 1);
   1240         ms->atomic_modeset = (ret == 0);
   1241     } else {
   1242         ms->atomic_modeset = FALSE;
   1243     }
   1244 
   1245     ms->kms_has_modifiers = FALSE;
   1246     ret = drmGetCap(ms->fd, DRM_CAP_ADDFB2_MODIFIERS, &value);
   1247     if (ret == 0 && value != 0)
   1248         ms->kms_has_modifiers = TRUE;
   1249 
   1250     if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
   1251         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n");
   1252         goto fail;
   1253     }
   1254 
   1255     /*
   1256      * If the driver can do gamma correction, it should call xf86SetGamma() here.
   1257      */
   1258     {
   1259         Gamma zeros = { 0.0, 0.0, 0.0 };
   1260 
   1261         if (!xf86SetGamma(pScrn, zeros)) {
   1262             return FALSE;
   1263         }
   1264     }
   1265 
   1266     if (!(pScrn->is_gpu && connector_count == 0) && pScrn->modes == NULL) {
   1267         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
   1268         return FALSE;
   1269     }
   1270 
   1271     pScrn->currentMode = pScrn->modes;
   1272 
   1273     /* Set display resolution */
   1274     xf86SetDpi(pScrn, 0, 0);
   1275 
   1276     /* Load the required sub modules */
   1277     if (!xf86LoadSubModule(pScrn, "fb")) {
   1278         return FALSE;
   1279     }
   1280 
   1281     if (ms->drmmode.shadow_enable) {
   1282         void *mod = xf86LoadSubModule(pScrn, "shadow");
   1283 
   1284         if (!mod)
   1285             return FALSE;
   1286 
   1287         ms->shadow.Setup        = LoaderSymbolFromModule(mod, "shadowSetup");
   1288         ms->shadow.Add          = LoaderSymbolFromModule(mod, "shadowAdd");
   1289         ms->shadow.Remove       = LoaderSymbolFromModule(mod, "shadowRemove");
   1290         ms->shadow.Update32to24 = LoaderSymbolFromModule(mod, "shadowUpdate32to24");
   1291         ms->shadow.UpdatePacked = LoaderSymbolFromModule(mod, "shadowUpdatePacked");
   1292     }
   1293 
   1294     return TRUE;
   1295  fail:
   1296     return FALSE;
   1297 }
   1298 
   1299 static void *
   1300 msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
   1301                CARD32 *size, void *closure)
   1302 {
   1303     ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
   1304     modesettingPtr ms = modesettingPTR(pScrn);
   1305     int stride;
   1306 
   1307     stride = (pScrn->displayWidth * ms->drmmode.kbpp) / 8;
   1308     *size = stride;
   1309 
   1310     return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset);
   1311 }
   1312 
   1313 /* somewhat arbitrary tile size, in pixels */
   1314 #define TILE 16
   1315 
   1316 static int
   1317 msUpdateIntersect(modesettingPtr ms, shadowBufPtr pBuf, BoxPtr box,
   1318                   xRectangle *prect)
   1319 {
   1320     int i, dirty = 0, stride = pBuf->pPixmap->devKind, cpp = ms->drmmode.cpp;
   1321     int width = (box->x2 - box->x1) * cpp;
   1322     unsigned char *old, *new;
   1323 
   1324     old = ms->drmmode.shadow_fb2;
   1325     old += (box->y1 * stride) + (box->x1 * cpp);
   1326     new = ms->drmmode.shadow_fb;
   1327     new += (box->y1 * stride) + (box->x1 * cpp);
   1328 
   1329     for (i = box->y2 - box->y1 - 1; i >= 0; i--) {
   1330         unsigned char *o = old + i * stride,
   1331                       *n = new + i * stride;
   1332         if (memcmp(o, n, width) != 0) {
   1333             dirty = 1;
   1334             memcpy(o, n, width);
   1335         }
   1336     }
   1337 
   1338     if (dirty) {
   1339         prect->x = box->x1;
   1340         prect->y = box->y1;
   1341         prect->width = box->x2 - box->x1;
   1342         prect->height = box->y2 - box->y1;
   1343     }
   1344 
   1345     return dirty;
   1346 }
   1347 
   1348 static void
   1349 msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
   1350 {
   1351     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1352     modesettingPtr ms = modesettingPTR(pScrn);
   1353     Bool use_3224 = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32;
   1354 
   1355     if (ms->drmmode.shadow_enable2 && ms->drmmode.shadow_fb2) do {
   1356         RegionPtr damage = DamageRegion(pBuf->pDamage), tiles;
   1357         BoxPtr extents = RegionExtents(damage);
   1358         xRectangle *prect;
   1359         int nrects;
   1360         int i, j, tx1, tx2, ty1, ty2;
   1361 
   1362         tx1 = extents->x1 / TILE;
   1363         tx2 = (extents->x2 + TILE - 1) / TILE;
   1364         ty1 = extents->y1 / TILE;
   1365         ty2 = (extents->y2 + TILE - 1) / TILE;
   1366 
   1367         nrects = (tx2 - tx1) * (ty2 - ty1);
   1368         if (!(prect = calloc(nrects, sizeof(xRectangle))))
   1369             break;
   1370 
   1371         nrects = 0;
   1372         for (j = ty2 - 1; j >= ty1; j--) {
   1373             for (i = tx2 - 1; i >= tx1; i--) {
   1374                 BoxRec box;
   1375 
   1376                 box.x1 = max(i * TILE, extents->x1);
   1377                 box.y1 = max(j * TILE, extents->y1);
   1378                 box.x2 = min((i+1) * TILE, extents->x2);
   1379                 box.y2 = min((j+1) * TILE, extents->y2);
   1380 
   1381                 if (RegionContainsRect(damage, &box) != rgnOUT) {
   1382                     if (msUpdateIntersect(ms, pBuf, &box, prect + nrects)) {
   1383                         nrects++;
   1384                     }
   1385                 }
   1386             }
   1387         }
   1388 
   1389         tiles = RegionFromRects(nrects, prect, CT_NONE);
   1390         RegionIntersect(damage, damage, tiles);
   1391         RegionDestroy(tiles);
   1392         free(prect);
   1393     } while (0);
   1394 
   1395     if (use_3224)
   1396         ms->shadow.Update32to24(pScreen, pBuf);
   1397     else
   1398         ms->shadow.UpdatePacked(pScreen, pBuf);
   1399 }
   1400 
   1401 static Bool
   1402 msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back)
   1403 {
   1404     ScreenPtr screen = crtc->pScreen;
   1405     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1406     modesettingPtr ms = modesettingPTR(scrn);
   1407     EntityInfoPtr pEnt = ms->pEnt;
   1408     xf86CrtcPtr xf86Crtc = crtc->devPrivate;
   1409 
   1410     if (!xf86Crtc)
   1411         return FALSE;
   1412 
   1413     /* Not supported if we can't flip */
   1414     if (!ms->drmmode.pageflip)
   1415         return FALSE;
   1416 
   1417     /* Not currently supported with reverse PRIME */
   1418     if (ms->drmmode.reverse_prime_offload_mode)
   1419         return FALSE;
   1420 
   1421 #ifdef XSERVER_PLATFORM_BUS
   1422     if (pEnt->location.type == BUS_PLATFORM) {
   1423         char *syspath =
   1424             xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
   1425             syspath;
   1426 
   1427         /* Not supported for devices using USB transport due to misbehaved
   1428          * vblank events */
   1429         if (syspath && strstr(syspath, "usb"))
   1430             return FALSE;
   1431 
   1432         /* EVDI uses USB transport but is platform device, not usb.
   1433          * Exclude it explicitly. */
   1434         if (syspath && strstr(syspath, "evdi"))
   1435             return FALSE;
   1436     }
   1437 #endif
   1438 
   1439     return drmmode_EnableSharedPixmapFlipping(xf86Crtc, &ms->drmmode,
   1440                                               front, back);
   1441 }
   1442 
   1443 static void
   1444 msDisableSharedPixmapFlipping(RRCrtcPtr crtc)
   1445 {
   1446     ScreenPtr screen = crtc->pScreen;
   1447     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1448     modesettingPtr ms = modesettingPTR(scrn);
   1449     xf86CrtcPtr xf86Crtc = crtc->devPrivate;
   1450 
   1451     if (xf86Crtc)
   1452         drmmode_DisableSharedPixmapFlipping(xf86Crtc, &ms->drmmode);
   1453 }
   1454 
   1455 static Bool
   1456 msStartFlippingPixmapTracking(RRCrtcPtr crtc, DrawablePtr src,
   1457                               PixmapPtr secondary_dst1, PixmapPtr secondary_dst2,
   1458                               int x, int y, int dst_x, int dst_y,
   1459                               Rotation rotation)
   1460 {
   1461     ScreenPtr pScreen = src->pScreen;
   1462     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
   1463 
   1464     msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap),
   1465                     ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap);
   1466 
   1467     if (!PixmapStartDirtyTracking(src, secondary_dst1, x, y,
   1468                                   dst_x, dst_y, rotation)) {
   1469         return FALSE;
   1470     }
   1471 
   1472     if (!PixmapStartDirtyTracking(src, secondary_dst2, x, y,
   1473                                   dst_x, dst_y, rotation)) {
   1474         PixmapStopDirtyTracking(src, secondary_dst1);
   1475         return FALSE;
   1476     }
   1477 
   1478     ppriv1->secondary_src = src;
   1479     ppriv2->secondary_src = src;
   1480 
   1481     ppriv1->dirty = ms_dirty_get_ent(pScreen, secondary_dst1);
   1482     ppriv2->dirty = ms_dirty_get_ent(pScreen, secondary_dst2);
   1483 
   1484     ppriv1->defer_dirty_update = TRUE;
   1485     ppriv2->defer_dirty_update = TRUE;
   1486 
   1487     return TRUE;
   1488 }
   1489 
   1490 static Bool
   1491 msPresentSharedPixmap(PixmapPtr secondary_dst)
   1492 {
   1493     ScreenPtr pScreen = secondary_dst->primary_pixmap->drawable.pScreen;
   1494     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
   1495 
   1496     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, secondary_dst->primary_pixmap);
   1497 
   1498     RegionPtr region = DamageRegion(ppriv->dirty->damage);
   1499 
   1500     if (RegionNotEmpty(region)) {
   1501         redisplay_dirty(ppriv->secondary_src->pScreen, ppriv->dirty, NULL);
   1502         DamageEmpty(ppriv->dirty->damage);
   1503 
   1504         return TRUE;
   1505     }
   1506 
   1507     return FALSE;
   1508 }
   1509 
   1510 static Bool
   1511 msStopFlippingPixmapTracking(DrawablePtr src,
   1512                              PixmapPtr secondary_dst1, PixmapPtr secondary_dst2)
   1513 {
   1514     ScreenPtr pScreen = src->pScreen;
   1515     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
   1516 
   1517     msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap),
   1518                     ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap);
   1519 
   1520     Bool ret = TRUE;
   1521 
   1522     ret &= PixmapStopDirtyTracking(src, secondary_dst1);
   1523     ret &= PixmapStopDirtyTracking(src, secondary_dst2);
   1524 
   1525     if (ret) {
   1526         ppriv1->secondary_src = NULL;
   1527         ppriv2->secondary_src = NULL;
   1528 
   1529         ppriv1->dirty = NULL;
   1530         ppriv2->dirty = NULL;
   1531 
   1532         ppriv1->defer_dirty_update = FALSE;
   1533         ppriv2->defer_dirty_update = FALSE;
   1534     }
   1535 
   1536     return ret;
   1537 }
   1538 
   1539 static Bool
   1540 CreateScreenResources(ScreenPtr pScreen)
   1541 {
   1542     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1543     modesettingPtr ms = modesettingPTR(pScrn);
   1544     PixmapPtr rootPixmap;
   1545     Bool ret;
   1546     void *pixels = NULL;
   1547     int err;
   1548 
   1549     pScreen->CreateScreenResources = ms->createScreenResources;
   1550     ret = pScreen->CreateScreenResources(pScreen);
   1551     pScreen->CreateScreenResources = CreateScreenResources;
   1552 
   1553     if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, pScrn->is_gpu, FALSE))
   1554         return FALSE;
   1555 
   1556     if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode))
   1557         return FALSE;
   1558 
   1559     drmmode_uevent_init(pScrn, &ms->drmmode);
   1560 
   1561     if (!ms->drmmode.sw_cursor)
   1562         drmmode_map_cursor_bos(pScrn, &ms->drmmode);
   1563 
   1564     if (!ms->drmmode.gbm) {
   1565         pixels = drmmode_map_front_bo(&ms->drmmode);
   1566         if (!pixels)
   1567             return FALSE;
   1568     }
   1569 
   1570     rootPixmap = pScreen->GetScreenPixmap(pScreen);
   1571 
   1572     if (ms->drmmode.shadow_enable)
   1573         pixels = ms->drmmode.shadow_fb;
   1574 
   1575     if (ms->drmmode.shadow_enable2) {
   1576         ms->drmmode.shadow_fb2 = calloc(1, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3));
   1577         if (!ms->drmmode.shadow_fb2)
   1578             ms->drmmode.shadow_enable2 = FALSE;
   1579     }
   1580 
   1581     if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels))
   1582         FatalError("Couldn't adjust screen pixmap\n");
   1583 
   1584     if (ms->drmmode.shadow_enable) {
   1585         if (!ms->shadow.Add(pScreen, rootPixmap, msUpdatePacked, msShadowWindow,
   1586                             0, 0))
   1587             return FALSE;
   1588     }
   1589 
   1590     err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0);
   1591 
   1592     if (err != -EINVAL && err != -ENOSYS) {
   1593         ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
   1594                                   pScreen, rootPixmap);
   1595 
   1596         if (ms->damage) {
   1597             DamageRegister(&rootPixmap->drawable, ms->damage);
   1598             ms->dirty_enabled = TRUE;
   1599             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
   1600         }
   1601         else {
   1602             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1603                        "Failed to create screen damage record\n");
   1604             return FALSE;
   1605         }
   1606     }
   1607 
   1608     if (dixPrivateKeyRegistered(rrPrivKey)) {
   1609         rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
   1610 
   1611         pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping;
   1612         pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping;
   1613 
   1614         pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
   1615     }
   1616 
   1617     if (ms->vrr_support &&
   1618         !dixRegisterPrivateKey(&ms->drmmode.vrrPrivateKeyRec,
   1619                                PRIVATE_WINDOW,
   1620                                sizeof(struct ms_vrr_priv)))
   1621             return FALSE;
   1622 
   1623     return ret;
   1624 }
   1625 
   1626 static Bool
   1627 msSharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle)
   1628 {
   1629 #ifdef GLAMOR_HAS_GBM
   1630     modesettingPtr ms =
   1631         modesettingPTR(xf86ScreenToScrn(ppix->drawable.pScreen));
   1632     int ret;
   1633     CARD16 stride;
   1634     CARD32 size;
   1635     ret = ms->glamor.shareable_fd_from_pixmap(ppix->drawable.pScreen, ppix,
   1636                                               &stride, &size);
   1637     if (ret == -1)
   1638         return FALSE;
   1639 
   1640     *handle = (void *)(long)(ret);
   1641     return TRUE;
   1642 #endif
   1643     return FALSE;
   1644 }
   1645 
   1646 static Bool
   1647 msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
   1648 {
   1649 #ifdef GLAMOR_HAS_GBM
   1650     ScreenPtr screen = ppix->drawable.pScreen;
   1651     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1652     modesettingPtr ms = modesettingPTR(scrn);
   1653     Bool ret;
   1654     int ihandle = (int) (long) fd_handle;
   1655 
   1656     if (ihandle == -1)
   1657         if (!ms->drmmode.reverse_prime_offload_mode)
   1658            return drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, 0, 0);
   1659 
   1660     if (ms->drmmode.reverse_prime_offload_mode) {
   1661         ret = ms->glamor.back_pixmap_from_fd(ppix, ihandle,
   1662                                              ppix->drawable.width,
   1663                                              ppix->drawable.height,
   1664                                              ppix->devKind,
   1665                                              ppix->drawable.depth,
   1666                                              ppix->drawable.bitsPerPixel);
   1667     } else {
   1668         int size = ppix->devKind * ppix->drawable.height;
   1669         ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size);
   1670     }
   1671     if (ret == FALSE)
   1672         return ret;
   1673 
   1674     return TRUE;
   1675 #else
   1676     return FALSE;
   1677 #endif
   1678 }
   1679 
   1680 static Bool
   1681 msRequestSharedPixmapNotifyDamage(PixmapPtr ppix)
   1682 {
   1683     ScreenPtr screen = ppix->drawable.pScreen;
   1684     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1685     modesettingPtr ms = modesettingPTR(scrn);
   1686 
   1687     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix->primary_pixmap);
   1688 
   1689     ppriv->notify_on_damage = TRUE;
   1690 
   1691     return TRUE;
   1692 }
   1693 
   1694 static Bool
   1695 msSharedPixmapNotifyDamage(PixmapPtr ppix)
   1696 {
   1697     Bool ret = FALSE;
   1698     int c;
   1699 
   1700     ScreenPtr screen = ppix->drawable.pScreen;
   1701     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
   1702     modesettingPtr ms = modesettingPTR(scrn);
   1703     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
   1704 
   1705     msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
   1706 
   1707     if (!ppriv->wait_for_damage)
   1708         return ret;
   1709     ppriv->wait_for_damage = FALSE;
   1710 
   1711     for (c = 0; c < xf86_config->num_crtc; c++) {
   1712         xf86CrtcPtr crtc = xf86_config->crtc[c];
   1713         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
   1714 
   1715         if (!drmmode_crtc)
   1716             continue;
   1717         if (!(drmmode_crtc->prime_pixmap && drmmode_crtc->prime_pixmap_back))
   1718             continue;
   1719 
   1720         // Received damage on primary screen pixmap, schedule present on vblank
   1721         ret |= drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, &ms->drmmode);
   1722     }
   1723 
   1724     return ret;
   1725 }
   1726 
   1727 static Bool
   1728 SetMaster(ScrnInfoPtr pScrn)
   1729 {
   1730     modesettingPtr ms = modesettingPTR(pScrn);
   1731     int ret;
   1732 
   1733 #ifdef XF86_PDEV_SERVER_FD
   1734     if (ms->pEnt->location.type == BUS_PLATFORM &&
   1735         (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
   1736         return TRUE;
   1737 #endif
   1738 
   1739     if (ms->fd_passed)
   1740         return TRUE;
   1741 
   1742     ret = drmSetMaster(ms->fd);
   1743     if (ret)
   1744         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n",
   1745                    strerror(errno));
   1746 
   1747     return ret == 0;
   1748 }
   1749 
   1750 /* When the root window is created, initialize the screen contents from
   1751  * console if -background none was specified on the command line
   1752  */
   1753 static Bool
   1754 CreateWindow_oneshot(WindowPtr pWin)
   1755 {
   1756     ScreenPtr pScreen = pWin->drawable.pScreen;
   1757     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1758     modesettingPtr ms = modesettingPTR(pScrn);
   1759     Bool ret;
   1760 
   1761     pScreen->CreateWindow = ms->CreateWindow;
   1762     ret = pScreen->CreateWindow(pWin);
   1763 
   1764     if (ret)
   1765         drmmode_copy_fb(pScrn, &ms->drmmode);
   1766     return ret;
   1767 }
   1768 
   1769 static Bool
   1770 ScreenInit(ScreenPtr pScreen, int argc, char **argv)
   1771 {
   1772     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1773     modesettingPtr ms = modesettingPTR(pScrn);
   1774     VisualPtr visual;
   1775 
   1776     pScrn->pScreen = pScreen;
   1777 
   1778     if (!SetMaster(pScrn))
   1779         return FALSE;
   1780 
   1781 #ifdef GLAMOR_HAS_GBM
   1782     if (ms->drmmode.glamor)
   1783         ms->drmmode.gbm = ms->glamor.egl_get_gbm_device(pScreen);
   1784 #endif
   1785 
   1786     /* HW dependent - FIXME */
   1787     pScrn->displayWidth = pScrn->virtualX;
   1788     if (!drmmode_create_initial_bos(pScrn, &ms->drmmode))
   1789         return FALSE;
   1790 
   1791     if (ms->drmmode.shadow_enable) {
   1792         ms->drmmode.shadow_fb =
   1793             calloc(1,
   1794                    pScrn->displayWidth * pScrn->virtualY *
   1795                    ((pScrn->bitsPerPixel + 7) >> 3));
   1796         if (!ms->drmmode.shadow_fb)
   1797             ms->drmmode.shadow_enable = FALSE;
   1798     }
   1799 
   1800     miClearVisualTypes();
   1801 
   1802     if (!miSetVisualTypes(pScrn->depth,
   1803                           miGetDefaultVisualMask(pScrn->depth),
   1804                           pScrn->rgbBits, pScrn->defaultVisual))
   1805         return FALSE;
   1806 
   1807     if (!miSetPixmapDepths())
   1808         return FALSE;
   1809 
   1810     if (!dixRegisterScreenSpecificPrivateKey
   1811         (pScreen, &ms->drmmode.pixmapPrivateKeyRec, PRIVATE_PIXMAP,
   1812          sizeof(msPixmapPrivRec))) {
   1813         return FALSE;
   1814     }
   1815 
   1816     pScrn->memPhysBase = 0;
   1817     pScrn->fbOffset = 0;
   1818 
   1819     if (!fbScreenInit(pScreen, NULL,
   1820                       pScrn->virtualX, pScrn->virtualY,
   1821                       pScrn->xDpi, pScrn->yDpi,
   1822                       pScrn->displayWidth, pScrn->bitsPerPixel))
   1823         return FALSE;
   1824 
   1825     if (pScrn->bitsPerPixel > 8) {
   1826         /* Fixup RGB ordering */
   1827         visual = pScreen->visuals + pScreen->numVisuals;
   1828         while (--visual >= pScreen->visuals) {
   1829             if ((visual->class | DynamicClass) == DirectColor) {
   1830                 visual->offsetRed = pScrn->offset.red;
   1831                 visual->offsetGreen = pScrn->offset.green;
   1832                 visual->offsetBlue = pScrn->offset.blue;
   1833                 visual->redMask = pScrn->mask.red;
   1834                 visual->greenMask = pScrn->mask.green;
   1835                 visual->blueMask = pScrn->mask.blue;
   1836             }
   1837         }
   1838     }
   1839 
   1840     fbPictureInit(pScreen, NULL, 0);
   1841 
   1842     if (drmmode_init(pScrn, &ms->drmmode) == FALSE) {
   1843         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1844                    "Failed to initialize glamor at ScreenInit() time.\n");
   1845         return FALSE;
   1846     }
   1847 
   1848     if (ms->drmmode.shadow_enable && !ms->shadow.Setup(pScreen)) {
   1849         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "shadow fb init failed\n");
   1850         return FALSE;
   1851     }
   1852 
   1853     ms->createScreenResources = pScreen->CreateScreenResources;
   1854     pScreen->CreateScreenResources = CreateScreenResources;
   1855 
   1856     xf86SetBlackWhitePixels(pScreen);
   1857 
   1858     xf86SetBackingStore(pScreen);
   1859     xf86SetSilkenMouse(pScreen);
   1860     miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
   1861 
   1862     /* If pageflip is enabled hook the screen's cursor-sprite (swcursor) funcs.
   1863      * So that we can disable page-flipping on fallback to a swcursor. */
   1864     if (ms->drmmode.pageflip) {
   1865         miPointerScreenPtr PointPriv =
   1866             dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
   1867 
   1868         if (!dixRegisterScreenPrivateKey(&ms->drmmode.spritePrivateKeyRec,
   1869                                          pScreen, PRIVATE_DEVICE,
   1870                                          sizeof(msSpritePrivRec)))
   1871             return FALSE;
   1872 
   1873         ms->SpriteFuncs = PointPriv->spriteFuncs;
   1874         PointPriv->spriteFuncs = &drmmode_sprite_funcs;
   1875     }
   1876 
   1877     /* Need to extend HWcursor support to handle mask interleave */
   1878     if (!ms->drmmode.sw_cursor)
   1879         xf86_cursors_init(pScreen, ms->cursor_width, ms->cursor_height,
   1880                           HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
   1881                           HARDWARE_CURSOR_UPDATE_UNHIDDEN |
   1882                           HARDWARE_CURSOR_ARGB);
   1883 
   1884     /* Must force it before EnterVT, so we are in control of VT and
   1885      * later memory should be bound when allocating, e.g rotate_mem */
   1886     pScrn->vtSema = TRUE;
   1887 
   1888     if (serverGeneration == 1 && bgNoneRoot && ms->drmmode.glamor) {
   1889         ms->CreateWindow = pScreen->CreateWindow;
   1890         pScreen->CreateWindow = CreateWindow_oneshot;
   1891     }
   1892 
   1893     pScreen->SaveScreen = xf86SaveScreen;
   1894     ms->CloseScreen = pScreen->CloseScreen;
   1895     pScreen->CloseScreen = CloseScreen;
   1896 
   1897     ms->BlockHandler = pScreen->BlockHandler;
   1898     pScreen->BlockHandler = msBlockHandler_oneshot;
   1899 
   1900     pScreen->SharePixmapBacking = msSharePixmapBacking;
   1901     pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking;
   1902     pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
   1903     pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
   1904 
   1905     pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage;
   1906     pScreen->RequestSharedPixmapNotifyDamage =
   1907         msRequestSharedPixmapNotifyDamage;
   1908 
   1909     pScreen->PresentSharedPixmap = msPresentSharedPixmap;
   1910     pScreen->StopFlippingPixmapTracking = msStopFlippingPixmapTracking;
   1911 
   1912     if (!xf86CrtcScreenInit(pScreen))
   1913         return FALSE;
   1914 
   1915     if (!drmmode_setup_colormap(pScreen, pScrn))
   1916         return FALSE;
   1917 
   1918     if (ms->atomic_modeset)
   1919         xf86DPMSInit(pScreen, drmmode_set_dpms, 0);
   1920     else
   1921         xf86DPMSInit(pScreen, xf86DPMSSet, 0);
   1922 
   1923 #ifdef GLAMOR_HAS_GBM
   1924     if (ms->drmmode.glamor) {
   1925         XF86VideoAdaptorPtr     glamor_adaptor;
   1926 
   1927         glamor_adaptor = ms->glamor.xv_init(pScreen, 16);
   1928         if (glamor_adaptor != NULL)
   1929             xf86XVScreenInit(pScreen, &glamor_adaptor, 1);
   1930         else
   1931             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1932                        "Failed to initialize XV support.\n");
   1933     }
   1934 #endif
   1935 
   1936     if (serverGeneration == 1)
   1937         xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
   1938 
   1939     if (!ms_vblank_screen_init(pScreen)) {
   1940         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1941                    "Failed to initialize vblank support.\n");
   1942         return FALSE;
   1943     }
   1944 
   1945 #ifdef GLAMOR_HAS_GBM
   1946     if (ms->drmmode.glamor) {
   1947         if (!(ms->drmmode.dri2_enable = ms_dri2_screen_init(pScreen))) {
   1948             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1949                        "Failed to initialize the DRI2 extension.\n");
   1950         }
   1951 
   1952         /* enable reverse prime if we are a GPU screen, and accelerated, and not
   1953          * i915, evdi or udl. i915 is happy scanning out from sysmem.
   1954          * evdi and udl are virtual drivers scanning out from sysmem
   1955          * backed dumb buffers.
   1956          */
   1957         if (pScreen->isGPU) {
   1958             drmVersionPtr version;
   1959 
   1960             /* enable if we are an accelerated GPU screen */
   1961             ms->drmmode.reverse_prime_offload_mode = TRUE;
   1962 
   1963             if ((version = drmGetVersion(ms->drmmode.fd))) {
   1964                 if (!strncmp("i915", version->name, version->name_len)) {
   1965                     ms->drmmode.reverse_prime_offload_mode = FALSE;
   1966                 }
   1967                 if (!strncmp("evdi", version->name, version->name_len)) {
   1968                     ms->drmmode.reverse_prime_offload_mode = FALSE;
   1969                 }
   1970                 if (!strncmp("udl", version->name, version->name_len)) {
   1971                     ms->drmmode.reverse_prime_offload_mode = FALSE;
   1972                 }
   1973                 if (!ms->drmmode.reverse_prime_offload_mode) {
   1974                     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
   1975                        "Disable reverse prime offload mode for %s.\n", version->name);
   1976                 }
   1977                 drmFreeVersion(version);
   1978             }
   1979         }
   1980     }
   1981 #endif
   1982     if (!(ms->drmmode.present_enable = ms_present_screen_init(pScreen))) {
   1983         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1984                    "Failed to initialize the Present extension.\n");
   1985     }
   1986 
   1987 
   1988     pScrn->vtSema = TRUE;
   1989 
   1990     if (ms->vrr_support) {
   1991         if (!property_vectors_wrapped) {
   1992             saved_change_property = ProcVector[X_ChangeProperty];
   1993             ProcVector[X_ChangeProperty] = ms_change_property;
   1994             saved_delete_property = ProcVector[X_DeleteProperty];
   1995             ProcVector[X_DeleteProperty] = ms_delete_property;
   1996             property_vectors_wrapped = TRUE;
   1997         }
   1998         vrr_atom = MakeAtom("_VARIABLE_REFRESH",
   1999                              strlen("_VARIABLE_REFRESH"), TRUE);
   2000     }
   2001 
   2002     return TRUE;
   2003 }
   2004 
   2005 static void
   2006 AdjustFrame(ScrnInfoPtr pScrn, int x, int y)
   2007 {
   2008     modesettingPtr ms = modesettingPTR(pScrn);
   2009 
   2010     drmmode_adjust_frame(pScrn, &ms->drmmode, x, y);
   2011 }
   2012 
   2013 static void
   2014 FreeScreen(ScrnInfoPtr pScrn)
   2015 {
   2016     FreeRec(pScrn);
   2017 }
   2018 
   2019 static void
   2020 LeaveVT(ScrnInfoPtr pScrn)
   2021 {
   2022     modesettingPtr ms = modesettingPTR(pScrn);
   2023 
   2024     xf86_hide_cursors(pScrn);
   2025 
   2026     pScrn->vtSema = FALSE;
   2027 
   2028 #ifdef XF86_PDEV_SERVER_FD
   2029     if (ms->pEnt->location.type == BUS_PLATFORM &&
   2030         (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))
   2031         return;
   2032 #endif
   2033 
   2034     if (!ms->fd_passed)
   2035         drmDropMaster(ms->fd);
   2036 }
   2037 
   2038 /*
   2039  * This gets called when gaining control of the VT, and from ScreenInit().
   2040  */
   2041 static Bool
   2042 EnterVT(ScrnInfoPtr pScrn)
   2043 {
   2044     modesettingPtr ms = modesettingPTR(pScrn);
   2045 
   2046     pScrn->vtSema = TRUE;
   2047 
   2048     SetMaster(pScrn);
   2049 
   2050     drmmode_update_kms_state(&ms->drmmode);
   2051 
   2052     /* allow not all modes to be set successfully since some events might have
   2053      * happened while not being master that could prevent the previous
   2054      * configuration from being re-applied.
   2055      */
   2056     if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, TRUE)) {
   2057         xf86DisableUnusedFunctions(pScrn);
   2058 
   2059         /* TODO: check that at least one screen is on, to allow the user to fix
   2060          * their setup if all modeset failed...
   2061          */
   2062 
   2063         /* Tell the desktop environment that something changed, so that they
   2064          * can hopefully correct the situation
   2065          */
   2066         RRSetChanged(xf86ScrnToScreen(pScrn));
   2067         RRTellChanged(xf86ScrnToScreen(pScrn));
   2068     }
   2069 
   2070     return TRUE;
   2071 }
   2072 
   2073 static Bool
   2074 SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
   2075 {
   2076     return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
   2077 }
   2078 
   2079 static Bool
   2080 CloseScreen(ScreenPtr pScreen)
   2081 {
   2082     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   2083     modesettingPtr ms = modesettingPTR(pScrn);
   2084     modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
   2085 
   2086     /* Clear mask of assigned crtc's in this generation */
   2087     ms_ent->assigned_crtcs = 0;
   2088 
   2089 #ifdef GLAMOR_HAS_GBM
   2090     if (ms->drmmode.dri2_enable) {
   2091         ms_dri2_close_screen(pScreen);
   2092     }
   2093 #endif
   2094 
   2095     ms_vblank_close_screen(pScreen);
   2096 
   2097     if (ms->damage) {
   2098         DamageUnregister(ms->damage);
   2099         DamageDestroy(ms->damage);
   2100         ms->damage = NULL;
   2101     }
   2102 
   2103     if (ms->drmmode.shadow_enable) {
   2104         ms->shadow.Remove(pScreen, pScreen->GetScreenPixmap(pScreen));
   2105         free(ms->drmmode.shadow_fb);
   2106         ms->drmmode.shadow_fb = NULL;
   2107         free(ms->drmmode.shadow_fb2);
   2108         ms->drmmode.shadow_fb2 = NULL;
   2109     }
   2110 
   2111     drmmode_uevent_fini(pScrn, &ms->drmmode);
   2112 
   2113     drmmode_free_bos(pScrn, &ms->drmmode);
   2114 
   2115     if (ms->drmmode.pageflip) {
   2116         miPointerScreenPtr PointPriv =
   2117             dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
   2118 
   2119         if (PointPriv->spriteFuncs == &drmmode_sprite_funcs)
   2120             PointPriv->spriteFuncs = ms->SpriteFuncs;        
   2121     }
   2122 
   2123     if (pScrn->vtSema) {
   2124         LeaveVT(pScrn);
   2125     }
   2126 
   2127     pScreen->CreateScreenResources = ms->createScreenResources;
   2128     pScreen->BlockHandler = ms->BlockHandler;
   2129 
   2130     pScrn->vtSema = FALSE;
   2131     pScreen->CloseScreen = ms->CloseScreen;
   2132     return (*pScreen->CloseScreen) (pScreen);
   2133 }
   2134 
   2135 static ModeStatus
   2136 ValidMode(ScrnInfoPtr arg, DisplayModePtr mode, Bool verbose, int flags)
   2137 {
   2138     return MODE_OK;
   2139 }