"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/hw/xfree86/drivers/modesetting/driver.c" (29 Mar 2020, 51917 Bytes) of package /linux/misc/xorg-server-1.20.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "driver.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.20.7_vs_1.20.8.

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