"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/hw/xfree86/drivers/modesetting/drmmode_display.c" (29 Mar 2020, 120795 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 "drmmode_display.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 © 2007 Red Hat, Inc.
    3  *
    4  * Permission is hereby granted, free of charge, to any person obtaining a
    5  * copy of this software and associated documentation files (the "Software"),
    6  * to deal in the Software without restriction, including without limitation
    7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    8  * and/or sell copies of the Software, and to permit persons to whom the
    9  * Software is furnished to do so, subject to the following conditions:
   10  *
   11  * The above copyright notice and this permission notice (including the next
   12  * paragraph) shall be included in all copies or substantial portions of the
   13  * Software.
   14  *
   15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   21  * SOFTWARE.
   22  *
   23  * Authors:
   24  *    Dave Airlie <airlied@redhat.com>
   25  *
   26  */
   27 
   28 #ifdef HAVE_DIX_CONFIG_H
   29 #include "dix-config.h"
   30 #endif
   31 
   32 #include <errno.h>
   33 #include <sys/ioctl.h>
   34 #include <sys/mman.h>
   35 #include <unistd.h>
   36 #include "dumb_bo.h"
   37 #include "xf86str.h"
   38 #include "X11/Xatom.h"
   39 #include "mi.h"
   40 #include "micmap.h"
   41 #include "xf86cmap.h"
   42 #include "xf86DDC.h"
   43 #include <drm_fourcc.h>
   44 #include <drm_mode.h>
   45 
   46 #include <xf86drm.h>
   47 #include "xf86Crtc.h"
   48 #include "drmmode_display.h"
   49 #include "present.h"
   50 
   51 #include <cursorstr.h>
   52 
   53 #include <X11/extensions/dpmsconst.h>
   54 
   55 #include "driver.h"
   56 
   57 static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
   58 static PixmapPtr drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int height,
   59                                               int depth, int bitsPerPixel, int devKind,
   60                                               void *pPixData);
   61 
   62 static inline uint32_t *
   63 formats_ptr(struct drm_format_modifier_blob *blob)
   64 {
   65     return (uint32_t *)(((char *)blob) + blob->formats_offset);
   66 }
   67 
   68 static inline struct drm_format_modifier *
   69 modifiers_ptr(struct drm_format_modifier_blob *blob)
   70 {
   71     return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
   72 }
   73 
   74 static uint32_t
   75 get_opaque_format(uint32_t format)
   76 {
   77     switch (format) {
   78     case DRM_FORMAT_ARGB8888:
   79         return DRM_FORMAT_XRGB8888;
   80     case DRM_FORMAT_ARGB2101010:
   81         return DRM_FORMAT_XRGB2101010;
   82     default:
   83         return format;
   84     }
   85 }
   86 
   87 Bool
   88 drmmode_is_format_supported(ScrnInfoPtr scrn, uint32_t format, uint64_t modifier)
   89 {
   90     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
   91     int c, i, j;
   92 
   93     /* BO are imported as opaque surface, so let's pretend there is no alpha */
   94     format = get_opaque_format(format);
   95 
   96     for (c = 0; c < xf86_config->num_crtc; c++) {
   97         xf86CrtcPtr crtc = xf86_config->crtc[c];
   98         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
   99         Bool found = FALSE;
  100 
  101         if (!crtc->enabled)
  102             continue;
  103 
  104         if (drmmode_crtc->num_formats == 0)
  105             continue;
  106 
  107         for (i = 0; i < drmmode_crtc->num_formats; i++) {
  108             drmmode_format_ptr iter = &drmmode_crtc->formats[i];
  109 
  110             if (iter->format != format)
  111                 continue;
  112 
  113             if (modifier == DRM_FORMAT_MOD_INVALID ||
  114                 iter->num_modifiers == 0) {
  115                 found = TRUE;
  116                 break;
  117             }
  118 
  119             for (j = 0; j < iter->num_modifiers; j++) {
  120                 if (iter->modifiers[j] == modifier) {
  121                     found = TRUE;
  122                     break;
  123                 }
  124             }
  125 
  126             break;
  127         }
  128 
  129         if (!found)
  130             return FALSE;
  131     }
  132 
  133     return TRUE;
  134 }
  135 
  136 #ifdef GBM_BO_WITH_MODIFIERS
  137 static uint32_t
  138 get_modifiers_set(ScrnInfoPtr scrn, uint32_t format, uint64_t **modifiers,
  139                   Bool enabled_crtc_only, Bool exclude_multiplane)
  140 {
  141     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
  142     modesettingPtr ms = modesettingPTR(scrn);
  143     drmmode_ptr drmmode = &ms->drmmode;
  144     int c, i, j, k, count_modifiers = 0;
  145     uint64_t *tmp, *ret = NULL;
  146 
  147     /* BOs are imported as opaque surfaces, so pretend the same thing here */
  148     format = get_opaque_format(format);
  149 
  150     *modifiers = NULL;
  151     for (c = 0; c < xf86_config->num_crtc; c++) {
  152         xf86CrtcPtr crtc = xf86_config->crtc[c];
  153         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  154 
  155         if (enabled_crtc_only && !crtc->enabled)
  156             continue;
  157 
  158         for (i = 0; i < drmmode_crtc->num_formats; i++) {
  159             drmmode_format_ptr iter = &drmmode_crtc->formats[i];
  160 
  161             if (iter->format != format)
  162                 continue;
  163 
  164             for (j = 0; j < iter->num_modifiers; j++) {
  165                 Bool found = FALSE;
  166 
  167         /* Don't choose multi-plane formats for our screen pixmap.
  168          * These will get used with frontbuffer rendering, which will
  169          * lead to worse-than-tearing with multi-plane formats, as the
  170          * primary and auxiliary planes go out of sync. */
  171         if (exclude_multiplane &&
  172                     gbm_device_get_format_modifier_plane_count(drmmode->gbm,
  173                                                                format,
  174                                                                iter->modifiers[j]) > 1) {
  175                     continue;
  176                 }
  177 
  178                 for (k = 0; k < count_modifiers; k++) {
  179                     if (iter->modifiers[j] == ret[k])
  180                         found = TRUE;
  181                 }
  182                 if (!found) {
  183                     count_modifiers++;
  184                     tmp = realloc(ret, count_modifiers * sizeof(uint64_t));
  185                     if (!tmp) {
  186                         free(ret);
  187                         return 0;
  188                     }
  189                     ret = tmp;
  190                     ret[count_modifiers - 1] = iter->modifiers[j];
  191                 }
  192             }
  193         }
  194     }
  195 
  196     *modifiers = ret;
  197     return count_modifiers;
  198 }
  199 
  200 static Bool
  201 get_drawable_modifiers(DrawablePtr draw, uint32_t format,
  202                        uint32_t *num_modifiers, uint64_t **modifiers)
  203 {
  204     ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
  205     modesettingPtr ms = modesettingPTR(scrn);
  206 
  207     if (!present_can_window_flip((WindowPtr) draw) ||
  208         !ms->drmmode.pageflip || ms->drmmode.dri2_flipping || !scrn->vtSema) {
  209         *num_modifiers = 0;
  210         *modifiers = NULL;
  211         return TRUE;
  212     }
  213 
  214     *num_modifiers = get_modifiers_set(scrn, format, modifiers, TRUE, FALSE);
  215     return TRUE;
  216 }
  217 #endif
  218 
  219 static Bool
  220 drmmode_zaphod_string_matches(ScrnInfoPtr scrn, const char *s, char *output_name)
  221 {
  222     char **token = xstrtokenize(s, ", \t\n\r");
  223     Bool ret = FALSE;
  224 
  225     if (!token)
  226         return FALSE;
  227 
  228     for (int i = 0; token[i]; i++) {
  229         if (strcmp(token[i], output_name) == 0)
  230             ret = TRUE;
  231 
  232         free(token[i]);
  233     }
  234 
  235     free(token);
  236 
  237     return ret;
  238 }
  239 
  240 static uint64_t
  241 drmmode_prop_get_value(drmmode_prop_info_ptr info,
  242                        drmModeObjectPropertiesPtr props,
  243                        uint64_t def)
  244 {
  245     unsigned int i;
  246 
  247     if (info->prop_id == 0)
  248         return def;
  249 
  250     for (i = 0; i < props->count_props; i++) {
  251         unsigned int j;
  252 
  253         if (props->props[i] != info->prop_id)
  254             continue;
  255 
  256         /* Simple (non-enum) types can return the value directly */
  257         if (info->num_enum_values == 0)
  258             return props->prop_values[i];
  259 
  260         /* Map from raw value to enum value */
  261         for (j = 0; j < info->num_enum_values; j++) {
  262             if (!info->enum_values[j].valid)
  263                 continue;
  264             if (info->enum_values[j].value != props->prop_values[i])
  265                 continue;
  266 
  267             return j;
  268         }
  269     }
  270 
  271     return def;
  272 }
  273 
  274 static uint32_t
  275 drmmode_prop_info_update(drmmode_ptr drmmode,
  276                          drmmode_prop_info_ptr info,
  277                          unsigned int num_infos,
  278                          drmModeObjectProperties *props)
  279 {
  280     drmModePropertyRes *prop;
  281     uint32_t valid_mask = 0;
  282     unsigned i, j;
  283 
  284     assert(num_infos <= 32 && "update return type");
  285 
  286     for (i = 0; i < props->count_props; i++) {
  287         Bool props_incomplete = FALSE;
  288         unsigned int k;
  289 
  290         for (j = 0; j < num_infos; j++) {
  291             if (info[j].prop_id == props->props[i])
  292                 break;
  293             if (!info[j].prop_id)
  294                 props_incomplete = TRUE;
  295         }
  296 
  297         /* We've already discovered this property. */
  298         if (j != num_infos)
  299             continue;
  300 
  301         /* We haven't found this property ID, but as we've already
  302          * found all known properties, we don't need to look any
  303          * further. */
  304         if (!props_incomplete)
  305             break;
  306 
  307         prop = drmModeGetProperty(drmmode->fd, props->props[i]);
  308         if (!prop)
  309             continue;
  310 
  311         for (j = 0; j < num_infos; j++) {
  312             if (!strcmp(prop->name, info[j].name))
  313                 break;
  314         }
  315 
  316         /* We don't know/care about this property. */
  317         if (j == num_infos) {
  318             drmModeFreeProperty(prop);
  319             continue;
  320         }
  321 
  322         info[j].prop_id = props->props[i];
  323         valid_mask |= 1U << j;
  324 
  325         if (info[j].num_enum_values == 0) {
  326             drmModeFreeProperty(prop);
  327             continue;
  328         }
  329 
  330         if (!(prop->flags & DRM_MODE_PROP_ENUM)) {
  331             xf86DrvMsg(drmmode->scrn->scrnIndex, X_WARNING,
  332                        "expected property %s to be an enum,"
  333                        " but it is not; ignoring\n", prop->name);
  334             drmModeFreeProperty(prop);
  335             continue;
  336         }
  337 
  338         for (k = 0; k < info[j].num_enum_values; k++) {
  339             int l;
  340 
  341             if (info[j].enum_values[k].valid)
  342                 continue;
  343 
  344             for (l = 0; l < prop->count_enums; l++) {
  345                 if (!strcmp(prop->enums[l].name,
  346                             info[j].enum_values[k].name))
  347                     break;
  348             }
  349 
  350             if (l == prop->count_enums)
  351                 continue;
  352 
  353             info[j].enum_values[k].valid = TRUE;
  354             info[j].enum_values[k].value = prop->enums[l].value;
  355         }
  356 
  357         drmModeFreeProperty(prop);
  358     }
  359 
  360     return valid_mask;
  361 }
  362 
  363 static Bool
  364 drmmode_prop_info_copy(drmmode_prop_info_ptr dst,
  365                const drmmode_prop_info_rec *src,
  366                unsigned int num_props,
  367                Bool copy_prop_id)
  368 {
  369     unsigned int i;
  370 
  371     memcpy(dst, src, num_props * sizeof(*dst));
  372 
  373     for (i = 0; i < num_props; i++) {
  374         unsigned int j;
  375 
  376         if (copy_prop_id)
  377             dst[i].prop_id = src[i].prop_id;
  378         else
  379             dst[i].prop_id = 0;
  380 
  381         if (src[i].num_enum_values == 0)
  382             continue;
  383 
  384         dst[i].enum_values =
  385             malloc(src[i].num_enum_values *
  386                     sizeof(*dst[i].enum_values));
  387         if (!dst[i].enum_values)
  388             goto err;
  389 
  390         memcpy(dst[i].enum_values, src[i].enum_values,
  391                 src[i].num_enum_values * sizeof(*dst[i].enum_values));
  392 
  393         for (j = 0; j < dst[i].num_enum_values; j++)
  394             dst[i].enum_values[j].valid = FALSE;
  395     }
  396 
  397     return TRUE;
  398 
  399 err:
  400     while (i--)
  401         free(dst[i].enum_values);
  402     return FALSE;
  403 }
  404 
  405 static void
  406 drmmode_prop_info_free(drmmode_prop_info_ptr info, int num_props)
  407 {
  408     int i;
  409 
  410     for (i = 0; i < num_props; i++)
  411         free(info[i].enum_values);
  412 }
  413 
  414 static void
  415 drmmode_ConvertToKMode(ScrnInfoPtr scrn,
  416                        drmModeModeInfo * kmode, DisplayModePtr mode);
  417 
  418 
  419 static int
  420 plane_add_prop(drmModeAtomicReq *req, drmmode_crtc_private_ptr drmmode_crtc,
  421                enum drmmode_plane_property prop, uint64_t val)
  422 {
  423     drmmode_prop_info_ptr info = &drmmode_crtc->props_plane[prop];
  424     int ret;
  425 
  426     if (!info)
  427         return -1;
  428 
  429     ret = drmModeAtomicAddProperty(req, drmmode_crtc->plane_id,
  430                                    info->prop_id, val);
  431     return (ret <= 0) ? -1 : 0;
  432 }
  433 
  434 static int
  435 plane_add_props(drmModeAtomicReq *req, xf86CrtcPtr crtc,
  436                 uint32_t fb_id, int x, int y)
  437 {
  438     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  439     int ret = 0;
  440 
  441     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_FB_ID,
  442                           fb_id);
  443     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_ID,
  444                           fb_id ? drmmode_crtc->mode_crtc->crtc_id : 0);
  445     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_X, x << 16);
  446     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_Y, y << 16);
  447     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_W,
  448                           crtc->mode.HDisplay << 16);
  449     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_SRC_H,
  450                           crtc->mode.VDisplay << 16);
  451     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_X, 0);
  452     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_Y, 0);
  453     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_W,
  454                           crtc->mode.HDisplay);
  455     ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_H,
  456                           crtc->mode.VDisplay);
  457 
  458     return ret;
  459 }
  460 
  461 static int
  462 crtc_add_prop(drmModeAtomicReq *req, drmmode_crtc_private_ptr drmmode_crtc,
  463               enum drmmode_crtc_property prop, uint64_t val)
  464 {
  465     drmmode_prop_info_ptr info = &drmmode_crtc->props[prop];
  466     int ret;
  467 
  468     if (!info)
  469         return -1;
  470 
  471     ret = drmModeAtomicAddProperty(req, drmmode_crtc->mode_crtc->crtc_id,
  472                                    info->prop_id, val);
  473     return (ret <= 0) ? -1 : 0;
  474 }
  475 
  476 static int
  477 connector_add_prop(drmModeAtomicReq *req, drmmode_output_private_ptr drmmode_output,
  478                    enum drmmode_connector_property prop, uint64_t val)
  479 {
  480     drmmode_prop_info_ptr info = &drmmode_output->props_connector[prop];
  481     int ret;
  482 
  483     if (!info)
  484         return -1;
  485 
  486     ret = drmModeAtomicAddProperty(req, drmmode_output->output_id,
  487                                    info->prop_id, val);
  488     return (ret <= 0) ? -1 : 0;
  489 }
  490 
  491 static int
  492 drmmode_CompareKModes(drmModeModeInfo * kmode, drmModeModeInfo * other)
  493 {
  494     return memcmp(kmode, other, sizeof(*kmode));
  495 }
  496 
  497 static int
  498 drm_mode_ensure_blob(xf86CrtcPtr crtc, drmModeModeInfo mode_info)
  499 {
  500     modesettingPtr ms = modesettingPTR(crtc->scrn);
  501     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  502     drmmode_mode_ptr mode;
  503     int ret;
  504 
  505     if (drmmode_crtc->current_mode &&
  506         drmmode_CompareKModes(&drmmode_crtc->current_mode->mode_info, &mode_info) == 0)
  507         return 0;
  508 
  509     mode = calloc(sizeof(drmmode_mode_rec), 1);
  510     if (!mode)
  511         return -1;
  512 
  513     mode->mode_info = mode_info;
  514     ret = drmModeCreatePropertyBlob(ms->fd,
  515                                     &mode->mode_info,
  516                                     sizeof(mode->mode_info),
  517                                     &mode->blob_id);
  518     drmmode_crtc->current_mode = mode;
  519     xorg_list_add(&mode->entry, &drmmode_crtc->mode_list);
  520 
  521     return ret;
  522 }
  523 
  524 static int
  525 crtc_add_dpms_props(drmModeAtomicReq *req, xf86CrtcPtr crtc,
  526                     int new_dpms, Bool *active)
  527 {
  528     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
  529     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  530     Bool crtc_active = FALSE;
  531     int i;
  532     int ret = 0;
  533 
  534     for (i = 0; i < xf86_config->num_output; i++) {
  535         xf86OutputPtr output = xf86_config->output[i];
  536         drmmode_output_private_ptr drmmode_output = output->driver_private;
  537 
  538         if (output->crtc != crtc) {
  539             if (drmmode_output->current_crtc == crtc) {
  540                 ret |= connector_add_prop(req, drmmode_output,
  541                                           DRMMODE_CONNECTOR_CRTC_ID, 0);
  542             }
  543             continue;
  544         }
  545 
  546         if (drmmode_output->output_id == -1)
  547             continue;
  548 
  549         if (new_dpms == DPMSModeOn)
  550             crtc_active = TRUE;
  551 
  552         ret |= connector_add_prop(req, drmmode_output,
  553                                   DRMMODE_CONNECTOR_CRTC_ID,
  554                                   crtc_active ?
  555                                       drmmode_crtc->mode_crtc->crtc_id : 0);
  556     }
  557 
  558     if (crtc_active) {
  559         drmModeModeInfo kmode;
  560 
  561         drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
  562         ret |= drm_mode_ensure_blob(crtc, kmode);
  563 
  564         ret |= crtc_add_prop(req, drmmode_crtc,
  565                              DRMMODE_CRTC_ACTIVE, 1);
  566         ret |= crtc_add_prop(req, drmmode_crtc,
  567                              DRMMODE_CRTC_MODE_ID,
  568                              drmmode_crtc->current_mode->blob_id);
  569     } else {
  570         ret |= crtc_add_prop(req, drmmode_crtc,
  571                              DRMMODE_CRTC_ACTIVE, 0);
  572         ret |= crtc_add_prop(req, drmmode_crtc,
  573                              DRMMODE_CRTC_MODE_ID, 0);
  574     }
  575 
  576     if (active)
  577         *active = crtc_active;
  578 
  579     return ret;
  580 }
  581 
  582 static void
  583 drm_mode_destroy(xf86CrtcPtr crtc, drmmode_mode_ptr mode)
  584 {
  585     modesettingPtr ms = modesettingPTR(crtc->scrn);
  586     if (mode->blob_id)
  587         drmModeDestroyPropertyBlob(ms->fd, mode->blob_id);
  588     xorg_list_del(&mode->entry);
  589     free(mode);
  590 }
  591 
  592 static int
  593 drmmode_crtc_can_test_mode(xf86CrtcPtr crtc)
  594 {
  595     modesettingPtr ms = modesettingPTR(crtc->scrn);
  596 
  597     return ms->atomic_modeset;
  598 }
  599 
  600 static Bool
  601 drmmode_crtc_get_fb_id(xf86CrtcPtr crtc, uint32_t *fb_id, int *x, int *y)
  602 {
  603     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  604     drmmode_ptr drmmode = drmmode_crtc->drmmode;
  605     int ret;
  606 
  607     *fb_id = 0;
  608 
  609     if (drmmode_crtc->prime_pixmap) {
  610         if (!drmmode->reverse_prime_offload_mode) {
  611             msPixmapPrivPtr ppriv =
  612                 msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
  613             *fb_id = ppriv->fb_id;
  614             *x = 0;
  615         } else
  616             *x = drmmode_crtc->prime_pixmap_x;
  617         *y = 0;
  618     }
  619     else if (drmmode_crtc->rotate_fb_id) {
  620         *fb_id = drmmode_crtc->rotate_fb_id;
  621         *x = *y = 0;
  622     }
  623     else {
  624         *fb_id = drmmode->fb_id;
  625         *x = crtc->x;
  626         *y = crtc->y;
  627     }
  628 
  629     if (*fb_id == 0) {
  630         ret = drmmode_bo_import(drmmode, &drmmode->front_bo,
  631                                 &drmmode->fb_id);
  632         if (ret < 0) {
  633             ErrorF("failed to add fb %d\n", ret);
  634             return FALSE;
  635         }
  636         *fb_id = drmmode->fb_id;
  637     }
  638 
  639     return TRUE;
  640 }
  641 
  642 void
  643 drmmode_set_dpms(ScrnInfoPtr scrn, int dpms, int flags)
  644 {
  645     modesettingPtr ms = modesettingPTR(scrn);
  646     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
  647     drmModeAtomicReq *req = drmModeAtomicAlloc();
  648     uint32_t mode_flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
  649     int ret = 0;
  650     int i;
  651 
  652     assert(ms->atomic_modeset);
  653 
  654     if (!req)
  655         return;
  656 
  657     for (i = 0; i < xf86_config->num_output; i++) {
  658         xf86OutputPtr output = xf86_config->output[i];
  659         drmmode_output_private_ptr drmmode_output = output->driver_private;
  660 
  661         if (output->crtc != NULL)
  662             continue;
  663 
  664         ret = connector_add_prop(req, drmmode_output,
  665                                  DRMMODE_CONNECTOR_CRTC_ID, 0);
  666     }
  667 
  668     for (i = 0; i < xf86_config->num_crtc; i++) {
  669         xf86CrtcPtr crtc = xf86_config->crtc[i];
  670         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  671         Bool active = FALSE;
  672 
  673         ret |= crtc_add_dpms_props(req, crtc, dpms, &active);
  674 
  675         if (dpms == DPMSModeOn && active && drmmode_crtc->need_modeset) {
  676             uint32_t fb_id;
  677             int x, y;
  678 
  679             if (!drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y))
  680                 continue;
  681             ret |= plane_add_props(req, crtc, fb_id, x, y);
  682             drmmode_crtc->need_modeset = FALSE;
  683         }
  684     }
  685 
  686     if (ret == 0)
  687         drmModeAtomicCommit(ms->fd, req, mode_flags, NULL);
  688     drmModeAtomicFree(req);
  689 
  690     ms->pending_modeset = TRUE;
  691     xf86DPMSSet(scrn, dpms, flags);
  692     ms->pending_modeset = FALSE;
  693 }
  694 
  695 static int
  696 drmmode_output_disable(xf86OutputPtr output)
  697 {
  698     modesettingPtr ms = modesettingPTR(output->scrn);
  699     drmmode_output_private_ptr drmmode_output = output->driver_private;
  700     xf86CrtcPtr crtc = drmmode_output->current_crtc;
  701     drmModeAtomicReq *req = drmModeAtomicAlloc();
  702     uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
  703     int ret = 0;
  704 
  705     assert(ms->atomic_modeset);
  706 
  707     if (!req)
  708         return 1;
  709 
  710     ret |= connector_add_prop(req, drmmode_output,
  711                               DRMMODE_CONNECTOR_CRTC_ID, 0);
  712     if (crtc)
  713         ret |= crtc_add_dpms_props(req, crtc, DPMSModeOff, NULL);
  714 
  715     if (ret == 0)
  716         ret = drmModeAtomicCommit(ms->fd, req, flags, NULL);
  717 
  718     if (ret == 0)
  719         drmmode_output->current_crtc = NULL;
  720 
  721     drmModeAtomicFree(req);
  722     return ret;
  723 }
  724 
  725 static int
  726 drmmode_crtc_disable(xf86CrtcPtr crtc)
  727 {
  728     modesettingPtr ms = modesettingPTR(crtc->scrn);
  729     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  730     drmModeAtomicReq *req = drmModeAtomicAlloc();
  731     uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
  732     int ret = 0;
  733 
  734     assert(ms->atomic_modeset);
  735 
  736     if (!req)
  737         return 1;
  738 
  739     ret |= crtc_add_prop(req, drmmode_crtc,
  740                          DRMMODE_CRTC_ACTIVE, 0);
  741     ret |= crtc_add_prop(req, drmmode_crtc,
  742                          DRMMODE_CRTC_MODE_ID, 0);
  743 
  744     if (ret == 0)
  745         ret = drmModeAtomicCommit(ms->fd, req, flags, NULL);
  746 
  747     drmModeAtomicFree(req);
  748     return ret;
  749 }
  750 
  751 static int
  752 drmmode_crtc_set_mode(xf86CrtcPtr crtc, Bool test_only)
  753 {
  754     modesettingPtr ms = modesettingPTR(crtc->scrn);
  755     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
  756     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  757     drmmode_ptr drmmode = drmmode_crtc->drmmode;
  758     ScreenPtr screen = crtc->scrn->pScreen;
  759     drmModeModeInfo kmode;
  760     int output_count = 0;
  761     uint32_t *output_ids = NULL;
  762     uint32_t fb_id;
  763     int x, y;
  764     int i, ret = 0;
  765 
  766     if (!drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y))
  767         return 1;
  768 
  769 #ifdef GLAMOR_HAS_GBM
  770     /* Make sure any pending drawing will be visible in a new scanout buffer */
  771     if (drmmode->glamor)
  772         glamor_finish(screen);
  773 #endif
  774 
  775     if (ms->atomic_modeset) {
  776         drmModeAtomicReq *req = drmModeAtomicAlloc();
  777         Bool active;
  778         uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
  779 
  780         if (!req)
  781             return 1;
  782 
  783         ret |= crtc_add_dpms_props(req, crtc, DPMSModeOn, &active);
  784         ret |= plane_add_props(req, crtc, active ? fb_id : 0, x, y);
  785 
  786         /* Orphaned CRTCs need to be disabled right now in atomic mode */
  787         for (i = 0; i < xf86_config->num_crtc; i++) {
  788             xf86CrtcPtr other_crtc = xf86_config->crtc[i];
  789             drmmode_crtc_private_ptr other_drmmode_crtc = other_crtc->driver_private;
  790             int lost_outputs = 0;
  791             int remaining_outputs = 0;
  792             int j;
  793 
  794             if (other_crtc == crtc)
  795                 continue;
  796 
  797             for (j = 0; j < xf86_config->num_output; j++) {
  798                 xf86OutputPtr output = xf86_config->output[j];
  799                 drmmode_output_private_ptr drmmode_output = output->driver_private;
  800 
  801                 if (drmmode_output->current_crtc == other_crtc) {
  802                     if (output->crtc == crtc)
  803                         lost_outputs++;
  804                     else
  805                         remaining_outputs++;
  806                 }
  807             }
  808 
  809             if (lost_outputs > 0 && remaining_outputs == 0) {
  810                 ret |= crtc_add_prop(req, other_drmmode_crtc,
  811                                      DRMMODE_CRTC_ACTIVE, 0);
  812                 ret |= crtc_add_prop(req, other_drmmode_crtc,
  813                                      DRMMODE_CRTC_MODE_ID, 0);
  814             }
  815         }
  816 
  817         if (test_only)
  818             flags |= DRM_MODE_ATOMIC_TEST_ONLY;
  819 
  820         if (ret == 0)
  821             ret = drmModeAtomicCommit(ms->fd, req, flags, NULL);
  822 
  823         if (ret == 0 && !test_only) {
  824             for (i = 0; i < xf86_config->num_output; i++) {
  825                 xf86OutputPtr output = xf86_config->output[i];
  826                 drmmode_output_private_ptr drmmode_output = output->driver_private;
  827 
  828                 if (output->crtc == crtc)
  829                     drmmode_output->current_crtc = crtc;
  830                 else if (drmmode_output->current_crtc == crtc)
  831                     drmmode_output->current_crtc = NULL;
  832             }
  833         }
  834 
  835         drmModeAtomicFree(req);
  836         return ret;
  837     }
  838 
  839     output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
  840     if (!output_ids)
  841         return -1;
  842 
  843     for (i = 0; i < xf86_config->num_output; i++) {
  844         xf86OutputPtr output = xf86_config->output[i];
  845         drmmode_output_private_ptr drmmode_output;
  846 
  847         if (output->crtc != crtc)
  848             continue;
  849 
  850         drmmode_output = output->driver_private;
  851         if (drmmode_output->output_id == -1)
  852             continue;
  853         output_ids[output_count] = drmmode_output->output_id;
  854         output_count++;
  855     }
  856 
  857     drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
  858     ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
  859                          fb_id, x, y, output_ids, output_count, &kmode);
  860 
  861     free(output_ids);
  862     return ret;
  863 }
  864 
  865 int
  866 drmmode_crtc_flip(xf86CrtcPtr crtc, uint32_t fb_id, uint32_t flags, void *data)
  867 {
  868     modesettingPtr ms = modesettingPTR(crtc->scrn);
  869     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
  870     int ret;
  871 
  872     if (ms->atomic_modeset) {
  873         drmModeAtomicReq *req = drmModeAtomicAlloc();
  874 
  875         if (!req)
  876             return 1;
  877 
  878         ret = plane_add_props(req, crtc, fb_id, crtc->x, crtc->y);
  879         flags |= DRM_MODE_ATOMIC_NONBLOCK;
  880         if (ret == 0)
  881             ret = drmModeAtomicCommit(ms->fd, req, flags, data);
  882         drmModeAtomicFree(req);
  883         return ret;
  884     }
  885 
  886     return drmModePageFlip(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
  887                            fb_id, flags, data);
  888 }
  889 
  890 int
  891 drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
  892 {
  893     int ret;
  894 
  895 #ifdef GLAMOR_HAS_GBM
  896     if (bo->gbm) {
  897         gbm_bo_destroy(bo->gbm);
  898         bo->gbm = NULL;
  899     }
  900 #endif
  901 
  902     if (bo->dumb) {
  903         ret = dumb_bo_destroy(drmmode->fd, bo->dumb);
  904         if (ret == 0)
  905             bo->dumb = NULL;
  906     }
  907 
  908     return 0;
  909 }
  910 
  911 uint32_t
  912 drmmode_bo_get_pitch(drmmode_bo *bo)
  913 {
  914 #ifdef GLAMOR_HAS_GBM
  915     if (bo->gbm)
  916         return gbm_bo_get_stride(bo->gbm);
  917 #endif
  918 
  919     return bo->dumb->pitch;
  920 }
  921 
  922 static Bool
  923 drmmode_bo_has_bo(drmmode_bo *bo)
  924 {
  925 #ifdef GLAMOR_HAS_GBM
  926     if (bo->gbm)
  927         return TRUE;
  928 #endif
  929 
  930     return bo->dumb != NULL;
  931 }
  932 
  933 uint32_t
  934 drmmode_bo_get_handle(drmmode_bo *bo)
  935 {
  936 #ifdef GLAMOR_HAS_GBM
  937     if (bo->gbm)
  938         return gbm_bo_get_handle(bo->gbm).u32;
  939 #endif
  940 
  941     return bo->dumb->handle;
  942 }
  943 
  944 static void *
  945 drmmode_bo_map(drmmode_ptr drmmode, drmmode_bo *bo)
  946 {
  947     int ret;
  948 
  949 #ifdef GLAMOR_HAS_GBM
  950     if (bo->gbm)
  951         return NULL;
  952 #endif
  953 
  954     if (bo->dumb->ptr)
  955         return bo->dumb->ptr;
  956 
  957     ret = dumb_bo_map(drmmode->fd, bo->dumb);
  958     if (ret)
  959         return NULL;
  960 
  961     return bo->dumb->ptr;
  962 }
  963 
  964 int
  965 drmmode_bo_import(drmmode_ptr drmmode, drmmode_bo *bo,
  966                   uint32_t *fb_id)
  967 {
  968 #ifdef GBM_BO_WITH_MODIFIERS
  969     modesettingPtr ms = modesettingPTR(drmmode->scrn);
  970     if (bo->gbm && ms->kms_has_modifiers &&
  971         gbm_bo_get_modifier(bo->gbm) != DRM_FORMAT_MOD_INVALID) {
  972         int num_fds;
  973 
  974         num_fds = gbm_bo_get_plane_count(bo->gbm);
  975         if (num_fds > 0) {
  976             int i;
  977             uint32_t format;
  978             uint32_t handles[4];
  979             uint32_t strides[4];
  980             uint32_t offsets[4];
  981             uint64_t modifiers[4];
  982 
  983             memset(handles, 0, sizeof(handles));
  984             memset(strides, 0, sizeof(strides));
  985             memset(offsets, 0, sizeof(offsets));
  986             memset(modifiers, 0, sizeof(modifiers));
  987 
  988             format = gbm_bo_get_format(bo->gbm);
  989             format = get_opaque_format(format);
  990             for (i = 0; i < num_fds; i++) {
  991                 handles[i] = gbm_bo_get_handle_for_plane(bo->gbm, i).u32;
  992                 strides[i] = gbm_bo_get_stride_for_plane(bo->gbm, i);
  993                 offsets[i] = gbm_bo_get_offset(bo->gbm, i);
  994                 modifiers[i] = gbm_bo_get_modifier(bo->gbm);
  995             }
  996 
  997             return drmModeAddFB2WithModifiers(drmmode->fd, bo->width, bo->height,
  998                                               format, handles, strides,
  999                                               offsets, modifiers, fb_id,
 1000                                               DRM_MODE_FB_MODIFIERS);
 1001         }
 1002     }
 1003 #endif
 1004     return drmModeAddFB(drmmode->fd, bo->width, bo->height,
 1005                         drmmode->scrn->depth, drmmode->kbpp,
 1006                         drmmode_bo_get_pitch(bo),
 1007                         drmmode_bo_get_handle(bo), fb_id);
 1008 }
 1009 
 1010 static Bool
 1011 drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
 1012                   unsigned width, unsigned height, unsigned bpp)
 1013 {
 1014     bo->width = width;
 1015     bo->height = height;
 1016 
 1017 #ifdef GLAMOR_HAS_GBM
 1018     if (drmmode->glamor) {
 1019         uint32_t format;
 1020 
 1021         if (drmmode->scrn->depth == 30)
 1022             format = GBM_FORMAT_ARGB2101010;
 1023         else
 1024             format = GBM_FORMAT_ARGB8888;
 1025 
 1026 #ifdef GBM_BO_WITH_MODIFIERS
 1027         uint32_t num_modifiers;
 1028         uint64_t *modifiers = NULL;
 1029 
 1030         num_modifiers = get_modifiers_set(drmmode->scrn, format, &modifiers,
 1031                                           FALSE, TRUE);
 1032         if (num_modifiers > 0 &&
 1033             !(num_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)) {
 1034             bo->gbm = gbm_bo_create_with_modifiers(drmmode->gbm, width, height,
 1035                                                    format, modifiers,
 1036                                                    num_modifiers);
 1037             free(modifiers);
 1038             if (bo->gbm) {
 1039                 bo->used_modifiers = TRUE;
 1040                 return TRUE;
 1041             }
 1042         }
 1043 #endif
 1044 
 1045         bo->gbm = gbm_bo_create(drmmode->gbm, width, height, format,
 1046                                 GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
 1047         bo->used_modifiers = FALSE;
 1048         return bo->gbm != NULL;
 1049     }
 1050 #endif
 1051 
 1052     bo->dumb = dumb_bo_create(drmmode->fd, width, height, bpp);
 1053     return bo->dumb != NULL;
 1054 }
 1055 
 1056 Bool
 1057 drmmode_SetSlaveBO(PixmapPtr ppix,
 1058                    drmmode_ptr drmmode, int fd_handle, int pitch, int size)
 1059 {
 1060     msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
 1061 
 1062     if (fd_handle == -1) {
 1063         dumb_bo_destroy(drmmode->fd, ppriv->backing_bo);
 1064         ppriv->backing_bo = NULL;
 1065         return TRUE;
 1066     }
 1067 
 1068     ppriv->backing_bo =
 1069         dumb_get_bo_from_fd(drmmode->fd, fd_handle, pitch, size);
 1070     if (!ppriv->backing_bo)
 1071         return FALSE;
 1072 
 1073     close(fd_handle);
 1074     return TRUE;
 1075 }
 1076 
 1077 static Bool
 1078 drmmode_SharedPixmapPresent(PixmapPtr ppix, xf86CrtcPtr crtc,
 1079                             drmmode_ptr drmmode)
 1080 {
 1081     ScreenPtr master = crtc->randr_crtc->pScreen->current_master;
 1082 
 1083     if (master->PresentSharedPixmap(ppix)) {
 1084         /* Success, queue flip to back target */
 1085         if (drmmode_SharedPixmapFlip(ppix, crtc, drmmode))
 1086             return TRUE;
 1087 
 1088         xf86DrvMsg(drmmode->scrn->scrnIndex, X_WARNING,
 1089                    "drmmode_SharedPixmapFlip() failed, trying again next vblank\n");
 1090 
 1091         return drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, drmmode);
 1092     }
 1093 
 1094     /* Failed to present, try again on next vblank after damage */
 1095     if (master->RequestSharedPixmapNotifyDamage) {
 1096         msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
 1097 
 1098         /* Set flag first in case we are immediately notified */
 1099         ppriv->wait_for_damage = TRUE;
 1100 
 1101         if (master->RequestSharedPixmapNotifyDamage(ppix))
 1102             return TRUE;
 1103         else
 1104             ppriv->wait_for_damage = FALSE;
 1105     }
 1106 
 1107     /* Damage notification not available, just try again on vblank */
 1108     return drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, drmmode);
 1109 }
 1110 
 1111 struct vblank_event_args {
 1112     PixmapPtr frontTarget;
 1113     PixmapPtr backTarget;
 1114     xf86CrtcPtr crtc;
 1115     drmmode_ptr drmmode;
 1116     Bool flip;
 1117 };
 1118 static void
 1119 drmmode_SharedPixmapVBlankEventHandler(uint64_t frame, uint64_t usec,
 1120                                        void *data)
 1121 {
 1122     struct vblank_event_args *args = data;
 1123 
 1124     drmmode_crtc_private_ptr drmmode_crtc = args->crtc->driver_private;
 1125 
 1126     if (args->flip) {
 1127         /* frontTarget is being displayed, update crtc to reflect */
 1128         drmmode_crtc->prime_pixmap = args->frontTarget;
 1129         drmmode_crtc->prime_pixmap_back = args->backTarget;
 1130 
 1131         /* Safe to present on backTarget, no longer displayed */
 1132         drmmode_SharedPixmapPresent(args->backTarget, args->crtc, args->drmmode);
 1133     } else {
 1134         /* backTarget is still being displayed, present on frontTarget */
 1135         drmmode_SharedPixmapPresent(args->frontTarget, args->crtc, args->drmmode);
 1136     }
 1137 
 1138     free(args);
 1139 }
 1140 
 1141 static void
 1142 drmmode_SharedPixmapVBlankEventAbort(void *data)
 1143 {
 1144     struct vblank_event_args *args = data;
 1145 
 1146     msGetPixmapPriv(args->drmmode, args->frontTarget)->flip_seq = 0;
 1147 
 1148     free(args);
 1149 }
 1150 
 1151 Bool
 1152 drmmode_SharedPixmapPresentOnVBlank(PixmapPtr ppix, xf86CrtcPtr crtc,
 1153                                     drmmode_ptr drmmode)
 1154 {
 1155     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1156     msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
 1157     struct vblank_event_args *event_args;
 1158 
 1159     if (ppix == drmmode_crtc->prime_pixmap)
 1160         return FALSE; /* Already flipped to this pixmap */
 1161     if (ppix != drmmode_crtc->prime_pixmap_back)
 1162         return FALSE; /* Pixmap is not a scanout pixmap for CRTC */
 1163 
 1164     event_args = calloc(1, sizeof(*event_args));
 1165     if (!event_args)
 1166         return FALSE;
 1167 
 1168     event_args->frontTarget = ppix;
 1169     event_args->backTarget = drmmode_crtc->prime_pixmap;
 1170     event_args->crtc = crtc;
 1171     event_args->drmmode = drmmode;
 1172     event_args->flip = FALSE;
 1173 
 1174     ppriv->flip_seq =
 1175         ms_drm_queue_alloc(crtc, event_args,
 1176                            drmmode_SharedPixmapVBlankEventHandler,
 1177                            drmmode_SharedPixmapVBlankEventAbort);
 1178 
 1179     return ms_queue_vblank(crtc, MS_QUEUE_RELATIVE, 1, NULL, ppriv->flip_seq);
 1180 }
 1181 
 1182 Bool
 1183 drmmode_SharedPixmapFlip(PixmapPtr frontTarget, xf86CrtcPtr crtc,
 1184                          drmmode_ptr drmmode)
 1185 {
 1186     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1187     msPixmapPrivPtr ppriv_front = msGetPixmapPriv(drmmode, frontTarget);
 1188 
 1189     struct vblank_event_args *event_args;
 1190 
 1191     event_args = calloc(1, sizeof(*event_args));
 1192     if (!event_args)
 1193         return FALSE;
 1194 
 1195     event_args->frontTarget = frontTarget;
 1196     event_args->backTarget = drmmode_crtc->prime_pixmap;
 1197     event_args->crtc = crtc;
 1198     event_args->drmmode = drmmode;
 1199     event_args->flip = TRUE;
 1200 
 1201     ppriv_front->flip_seq =
 1202         ms_drm_queue_alloc(crtc, event_args,
 1203                            drmmode_SharedPixmapVBlankEventHandler,
 1204                            drmmode_SharedPixmapVBlankEventAbort);
 1205 
 1206     if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 1207                         ppriv_front->fb_id, DRM_MODE_PAGE_FLIP_EVENT,
 1208                         (void *)(intptr_t) ppriv_front->flip_seq) < 0) {
 1209         ms_drm_abort_seq(crtc->scrn, ppriv_front->flip_seq);
 1210         return FALSE;
 1211     }
 1212 
 1213     return TRUE;
 1214 }
 1215 
 1216 static Bool
 1217 drmmode_InitSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode)
 1218 {
 1219     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1220 
 1221     if (!drmmode_crtc->enable_flipping)
 1222         return FALSE;
 1223 
 1224     if (drmmode_crtc->flipping_active)
 1225         return TRUE;
 1226 
 1227     drmmode_crtc->flipping_active =
 1228         drmmode_SharedPixmapPresent(drmmode_crtc->prime_pixmap_back,
 1229                                     crtc, drmmode);
 1230 
 1231     return drmmode_crtc->flipping_active;
 1232 }
 1233 
 1234 static void
 1235 drmmode_FiniSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode)
 1236 {
 1237     uint32_t seq;
 1238     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1239 
 1240     if (!drmmode_crtc->flipping_active)
 1241         return;
 1242 
 1243     drmmode_crtc->flipping_active = FALSE;
 1244 
 1245     /* Abort page flip event handler on prime_pixmap */
 1246     seq = msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap)->flip_seq;
 1247     if (seq)
 1248         ms_drm_abort_seq(crtc->scrn, seq);
 1249 
 1250     /* Abort page flip event handler on prime_pixmap_back */
 1251     seq = msGetPixmapPriv(drmmode,
 1252                           drmmode_crtc->prime_pixmap_back)->flip_seq;
 1253     if (seq)
 1254         ms_drm_abort_seq(crtc->scrn, seq);
 1255 }
 1256 
 1257 static Bool drmmode_set_target_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix,
 1258                                               PixmapPtr *target);
 1259 
 1260 Bool
 1261 drmmode_EnableSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode,
 1262                                    PixmapPtr front, PixmapPtr back)
 1263 {
 1264     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1265 
 1266     drmmode_crtc->enable_flipping = TRUE;
 1267 
 1268     /* Set front scanout pixmap */
 1269     drmmode_crtc->enable_flipping &=
 1270         drmmode_set_target_scanout_pixmap(crtc, front,
 1271                                           &drmmode_crtc->prime_pixmap);
 1272     if (!drmmode_crtc->enable_flipping)
 1273         return FALSE;
 1274 
 1275     /* Set back scanout pixmap */
 1276     drmmode_crtc->enable_flipping &=
 1277         drmmode_set_target_scanout_pixmap(crtc, back,
 1278                                           &drmmode_crtc->prime_pixmap_back);
 1279     if (!drmmode_crtc->enable_flipping) {
 1280         drmmode_set_target_scanout_pixmap(crtc, NULL,
 1281                                           &drmmode_crtc->prime_pixmap);
 1282         return FALSE;
 1283     }
 1284 
 1285     return TRUE;
 1286 }
 1287 
 1288 void
 1289 drmmode_DisableSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode)
 1290 {
 1291     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1292 
 1293     drmmode_crtc->enable_flipping = FALSE;
 1294 
 1295     drmmode_FiniSharedPixmapFlipping(crtc, drmmode);
 1296 
 1297     drmmode_set_target_scanout_pixmap(crtc, NULL, &drmmode_crtc->prime_pixmap);
 1298 
 1299     drmmode_set_target_scanout_pixmap(crtc, NULL,
 1300                                       &drmmode_crtc->prime_pixmap_back);
 1301 }
 1302 
 1303 static void
 1304 drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
 1305                          drmModeModeInfo * kmode, DisplayModePtr mode)
 1306 {
 1307     memset(mode, 0, sizeof(DisplayModeRec));
 1308     mode->status = MODE_OK;
 1309 
 1310     mode->Clock = kmode->clock;
 1311 
 1312     mode->HDisplay = kmode->hdisplay;
 1313     mode->HSyncStart = kmode->hsync_start;
 1314     mode->HSyncEnd = kmode->hsync_end;
 1315     mode->HTotal = kmode->htotal;
 1316     mode->HSkew = kmode->hskew;
 1317 
 1318     mode->VDisplay = kmode->vdisplay;
 1319     mode->VSyncStart = kmode->vsync_start;
 1320     mode->VSyncEnd = kmode->vsync_end;
 1321     mode->VTotal = kmode->vtotal;
 1322     mode->VScan = kmode->vscan;
 1323 
 1324     mode->Flags = kmode->flags; //& FLAG_BITS;
 1325     mode->name = strdup(kmode->name);
 1326 
 1327     if (kmode->type & DRM_MODE_TYPE_DRIVER)
 1328         mode->type = M_T_DRIVER;
 1329     if (kmode->type & DRM_MODE_TYPE_PREFERRED)
 1330         mode->type |= M_T_PREFERRED;
 1331     xf86SetModeCrtc(mode, scrn->adjustFlags);
 1332 }
 1333 
 1334 static void
 1335 drmmode_ConvertToKMode(ScrnInfoPtr scrn,
 1336                        drmModeModeInfo * kmode, DisplayModePtr mode)
 1337 {
 1338     memset(kmode, 0, sizeof(*kmode));
 1339 
 1340     kmode->clock = mode->Clock;
 1341     kmode->hdisplay = mode->HDisplay;
 1342     kmode->hsync_start = mode->HSyncStart;
 1343     kmode->hsync_end = mode->HSyncEnd;
 1344     kmode->htotal = mode->HTotal;
 1345     kmode->hskew = mode->HSkew;
 1346 
 1347     kmode->vdisplay = mode->VDisplay;
 1348     kmode->vsync_start = mode->VSyncStart;
 1349     kmode->vsync_end = mode->VSyncEnd;
 1350     kmode->vtotal = mode->VTotal;
 1351     kmode->vscan = mode->VScan;
 1352 
 1353     kmode->flags = mode->Flags; //& FLAG_BITS;
 1354     if (mode->name)
 1355         strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
 1356     kmode->name[DRM_DISPLAY_MODE_LEN - 1] = 0;
 1357 
 1358 }
 1359 
 1360 static void
 1361 drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
 1362 {
 1363     modesettingPtr ms = modesettingPTR(crtc->scrn);
 1364     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1365     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1366 
 1367     /* XXX Check if DPMS mode is already the right one */
 1368 
 1369     drmmode_crtc->dpms_mode = mode;
 1370 
 1371     if (ms->atomic_modeset) {
 1372         if (mode != DPMSModeOn && !ms->pending_modeset)
 1373             drmmode_crtc_disable(crtc);
 1374     } else if (crtc->enabled == FALSE) {
 1375         drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 1376                        0, 0, 0, NULL, 0, NULL);
 1377     }
 1378 }
 1379 
 1380 #ifdef GLAMOR_HAS_GBM
 1381 static PixmapPtr
 1382 create_pixmap_for_fbcon(drmmode_ptr drmmode, ScrnInfoPtr pScrn, int fbcon_id)
 1383 {
 1384     PixmapPtr pixmap = drmmode->fbcon_pixmap;
 1385     drmModeFBPtr fbcon;
 1386     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
 1387     Bool ret;
 1388 
 1389     if (pixmap)
 1390         return pixmap;
 1391 
 1392     fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
 1393     if (fbcon == NULL)
 1394         return NULL;
 1395 
 1396     if (fbcon->depth != pScrn->depth ||
 1397         fbcon->width != pScrn->virtualX ||
 1398         fbcon->height != pScrn->virtualY)
 1399         goto out_free_fb;
 1400 
 1401     pixmap = drmmode_create_pixmap_header(pScreen, fbcon->width,
 1402                                           fbcon->height, fbcon->depth,
 1403                                           fbcon->bpp, fbcon->pitch, NULL);
 1404     if (!pixmap)
 1405         goto out_free_fb;
 1406 
 1407     ret = glamor_egl_create_textured_pixmap(pixmap, fbcon->handle, fbcon->pitch);
 1408     if (!ret) {
 1409       FreePixmap(pixmap);
 1410       pixmap = NULL;
 1411     }
 1412 
 1413     drmmode->fbcon_pixmap = pixmap;
 1414 out_free_fb:
 1415     drmModeFreeFB(fbcon);
 1416     return pixmap;
 1417 }
 1418 #endif
 1419 
 1420 void
 1421 drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 1422 {
 1423 #ifdef GLAMOR_HAS_GBM
 1424     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 1425     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
 1426     PixmapPtr src, dst;
 1427     int fbcon_id = 0;
 1428     GCPtr gc;
 1429     int i;
 1430 
 1431     for (i = 0; i < xf86_config->num_crtc; i++) {
 1432         drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private;
 1433         if (drmmode_crtc->mode_crtc->buffer_id)
 1434             fbcon_id = drmmode_crtc->mode_crtc->buffer_id;
 1435     }
 1436 
 1437     if (!fbcon_id)
 1438         return;
 1439 
 1440     if (fbcon_id == drmmode->fb_id) {
 1441         /* in some rare case there might be no fbcon and we might already
 1442          * be the one with the current fb to avoid a false deadlck in
 1443          * kernel ttm code just do nothing as anyway there is nothing
 1444          * to do
 1445          */
 1446         return;
 1447     }
 1448 
 1449     src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id);
 1450     if (!src)
 1451         return;
 1452 
 1453     dst = pScreen->GetScreenPixmap(pScreen);
 1454 
 1455     gc = GetScratchGC(pScrn->depth, pScreen);
 1456     ValidateGC(&dst->drawable, gc);
 1457 
 1458     (*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0,
 1459                          pScrn->virtualX, pScrn->virtualY, 0, 0);
 1460 
 1461     FreeScratchGC(gc);
 1462 
 1463     pScreen->canDoBGNoneRoot = TRUE;
 1464 
 1465     if (drmmode->fbcon_pixmap)
 1466         pScrn->pScreen->DestroyPixmap(drmmode->fbcon_pixmap);
 1467     drmmode->fbcon_pixmap = NULL;
 1468 #endif
 1469 }
 1470 
 1471 static Bool
 1472 drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 1473                        Rotation rotation, int x, int y)
 1474 {
 1475     modesettingPtr ms = modesettingPTR(crtc->scrn);
 1476     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
 1477     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1478     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1479     int saved_x, saved_y;
 1480     Rotation saved_rotation;
 1481     DisplayModeRec saved_mode;
 1482     Bool ret = TRUE;
 1483     Bool can_test;
 1484     int i;
 1485 
 1486     saved_mode = crtc->mode;
 1487     saved_x = crtc->x;
 1488     saved_y = crtc->y;
 1489     saved_rotation = crtc->rotation;
 1490 
 1491     if (mode) {
 1492         crtc->mode = *mode;
 1493         crtc->x = x;
 1494         crtc->y = y;
 1495         crtc->rotation = rotation;
 1496 
 1497         if (!xf86CrtcRotate(crtc)) {
 1498             goto done;
 1499         }
 1500 
 1501         crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
 1502                                crtc->gamma_blue, crtc->gamma_size);
 1503 
 1504         can_test = drmmode_crtc_can_test_mode(crtc);
 1505         if (drmmode_crtc_set_mode(crtc, can_test)) {
 1506             xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
 1507                        "failed to set mode: %s\n", strerror(errno));
 1508             ret = FALSE;
 1509             goto done;
 1510         } else
 1511             ret = TRUE;
 1512 
 1513         if (crtc->scrn->pScreen)
 1514             xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
 1515 
 1516         ms->pending_modeset = TRUE;
 1517         drmmode_crtc->need_modeset = FALSE;
 1518         crtc->funcs->dpms(crtc, DPMSModeOn);
 1519 
 1520         if (drmmode_crtc->prime_pixmap_back)
 1521             drmmode_InitSharedPixmapFlipping(crtc, drmmode);
 1522 
 1523         /* go through all the outputs and force DPMS them back on? */
 1524         for (i = 0; i < xf86_config->num_output; i++) {
 1525             xf86OutputPtr output = xf86_config->output[i];
 1526             drmmode_output_private_ptr drmmode_output;
 1527 
 1528             if (output->crtc != crtc)
 1529                 continue;
 1530 
 1531             drmmode_output = output->driver_private;
 1532             if (drmmode_output->output_id == -1)
 1533                 continue;
 1534             output->funcs->dpms(output, DPMSModeOn);
 1535         }
 1536 
 1537         /* if we only tested the mode previously, really set it now */
 1538         if (can_test)
 1539             drmmode_crtc_set_mode(crtc, FALSE);
 1540         ms->pending_modeset = FALSE;
 1541     }
 1542 
 1543  done:
 1544     if (!ret) {
 1545         crtc->x = saved_x;
 1546         crtc->y = saved_y;
 1547         crtc->rotation = saved_rotation;
 1548         crtc->mode = saved_mode;
 1549     } else
 1550         crtc->active = TRUE;
 1551 
 1552     return ret;
 1553 }
 1554 
 1555 static void
 1556 drmmode_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
 1557 {
 1558 
 1559 }
 1560 
 1561 static void
 1562 drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
 1563 {
 1564     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1565     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1566 
 1567     drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
 1568 }
 1569 
 1570 static Bool
 1571 drmmode_set_cursor(xf86CrtcPtr crtc)
 1572 {
 1573     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1574     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1575     uint32_t handle = drmmode_crtc->cursor_bo->handle;
 1576     modesettingPtr ms = modesettingPTR(crtc->scrn);
 1577     CursorPtr cursor = xf86CurrentCursor(crtc->scrn->pScreen);
 1578     int ret = -EINVAL;
 1579 
 1580     if (cursor == NullCursor)
 1581         return TRUE;
 1582 
 1583     ret = drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 1584                             handle, ms->cursor_width, ms->cursor_height,
 1585                             cursor->bits->xhot, cursor->bits->yhot);
 1586 
 1587     /* -EINVAL can mean that an old kernel supports drmModeSetCursor but
 1588      * not drmModeSetCursor2, though it can mean other things too. */
 1589     if (ret == -EINVAL)
 1590         ret = drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 1591                                handle, ms->cursor_width, ms->cursor_height);
 1592 
 1593     /* -ENXIO normally means that the current drm driver supports neither
 1594      * cursor_set nor cursor_set2.  Disable hardware cursor support for
 1595      * the rest of the session in that case. */
 1596     if (ret == -ENXIO) {
 1597         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
 1598         xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
 1599 
 1600         cursor_info->MaxWidth = cursor_info->MaxHeight = 0;
 1601         drmmode_crtc->drmmode->sw_cursor = TRUE;
 1602     }
 1603 
 1604     if (ret)
 1605         /* fallback to swcursor */
 1606         return FALSE;
 1607     return TRUE;
 1608 }
 1609 
 1610 static void drmmode_hide_cursor(xf86CrtcPtr crtc);
 1611 
 1612 /*
 1613  * The load_cursor_argb_check driver hook.
 1614  *
 1615  * Sets the hardware cursor by calling the drmModeSetCursor2 ioctl.
 1616  * On failure, returns FALSE indicating that the X server should fall
 1617  * back to software cursors.
 1618  */
 1619 static Bool
 1620 drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image)
 1621 {
 1622     modesettingPtr ms = modesettingPTR(crtc->scrn);
 1623     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1624     int i;
 1625     uint32_t *ptr;
 1626 
 1627     /* cursor should be mapped already */
 1628     ptr = (uint32_t *) (drmmode_crtc->cursor_bo->ptr);
 1629 
 1630     for (i = 0; i < ms->cursor_width * ms->cursor_height; i++)
 1631         ptr[i] = image[i];      // cpu_to_le32(image[i]);
 1632 
 1633     if (drmmode_crtc->cursor_up)
 1634         return drmmode_set_cursor(crtc);
 1635     return TRUE;
 1636 }
 1637 
 1638 static void
 1639 drmmode_hide_cursor(xf86CrtcPtr crtc)
 1640 {
 1641     modesettingPtr ms = modesettingPTR(crtc->scrn);
 1642     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1643     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1644 
 1645     drmmode_crtc->cursor_up = FALSE;
 1646     drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
 1647                      ms->cursor_width, ms->cursor_height);
 1648 }
 1649 
 1650 static Bool
 1651 drmmode_show_cursor(xf86CrtcPtr crtc)
 1652 {
 1653     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1654     drmmode_crtc->cursor_up = TRUE;
 1655     return drmmode_set_cursor(crtc);
 1656 }
 1657 
 1658 static void
 1659 drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
 1660                        uint16_t * blue, int size)
 1661 {
 1662     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1663     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1664 
 1665     drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 1666                         size, red, green, blue);
 1667 }
 1668 
 1669 static Bool
 1670 drmmode_set_target_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix,
 1671                                       PixmapPtr *target)
 1672 {
 1673     ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
 1674     PixmapPtr screenpix = screen->GetScreenPixmap(screen);
 1675     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
 1676     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1677     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1678     int c, total_width = 0, max_height = 0, this_x = 0;
 1679 
 1680     if (*target) {
 1681         PixmapStopDirtyTracking(&(*target)->drawable, screenpix);
 1682         if (drmmode->fb_id) {
 1683             drmModeRmFB(drmmode->fd, drmmode->fb_id);
 1684             drmmode->fb_id = 0;
 1685         }
 1686         drmmode_crtc->prime_pixmap_x = 0;
 1687         *target = NULL;
 1688     }
 1689 
 1690     if (!ppix)
 1691         return TRUE;
 1692 
 1693     /* iterate over all the attached crtcs to work out the bounding box */
 1694     for (c = 0; c < xf86_config->num_crtc; c++) {
 1695         xf86CrtcPtr iter = xf86_config->crtc[c];
 1696         if (!iter->enabled && iter != crtc)
 1697             continue;
 1698         if (iter == crtc) {
 1699             this_x = total_width;
 1700             total_width += ppix->drawable.width;
 1701             if (max_height < ppix->drawable.height)
 1702                 max_height = ppix->drawable.height;
 1703         } else {
 1704             total_width += iter->mode.HDisplay;
 1705             if (max_height < iter->mode.VDisplay)
 1706                 max_height = iter->mode.VDisplay;
 1707         }
 1708     }
 1709 
 1710     if (total_width != screenpix->drawable.width ||
 1711         max_height != screenpix->drawable.height) {
 1712 
 1713         if (!drmmode_xf86crtc_resize(crtc->scrn, total_width, max_height))
 1714             return FALSE;
 1715 
 1716         screenpix = screen->GetScreenPixmap(screen);
 1717         screen->width = screenpix->drawable.width = total_width;
 1718         screen->height = screenpix->drawable.height = max_height;
 1719     }
 1720     drmmode_crtc->prime_pixmap_x = this_x;
 1721     PixmapStartDirtyTracking(&ppix->drawable, screenpix, 0, 0, this_x, 0,
 1722                              RR_Rotate_0);
 1723     *target = ppix;
 1724     return TRUE;
 1725 }
 1726 
 1727 static Bool
 1728 drmmode_set_target_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix,
 1729                                       PixmapPtr *target)
 1730 {
 1731     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1732     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1733     msPixmapPrivPtr ppriv;
 1734     void *ptr;
 1735 
 1736     if (*target) {
 1737         ppriv = msGetPixmapPriv(drmmode, *target);
 1738         drmModeRmFB(drmmode->fd, ppriv->fb_id);
 1739         ppriv->fb_id = 0;
 1740         if (ppriv->slave_damage) {
 1741             DamageUnregister(ppriv->slave_damage);
 1742             ppriv->slave_damage = NULL;
 1743         }
 1744         *target = NULL;
 1745     }
 1746 
 1747     if (!ppix)
 1748         return TRUE;
 1749 
 1750     ppriv = msGetPixmapPriv(drmmode, ppix);
 1751     if (!ppriv->slave_damage) {
 1752         ppriv->slave_damage = DamageCreate(NULL, NULL,
 1753                                            DamageReportNone,
 1754                                            TRUE,
 1755                                            crtc->randr_crtc->pScreen,
 1756                                            NULL);
 1757     }
 1758     ptr = drmmode_map_slave_bo(drmmode, ppriv);
 1759     ppix->devPrivate.ptr = ptr;
 1760     DamageRegister(&ppix->drawable, ppriv->slave_damage);
 1761 
 1762     if (ppriv->fb_id == 0) {
 1763         drmModeAddFB(drmmode->fd, ppix->drawable.width,
 1764                      ppix->drawable.height,
 1765                      ppix->drawable.depth,
 1766                      ppix->drawable.bitsPerPixel,
 1767                      ppix->devKind, ppriv->backing_bo->handle, &ppriv->fb_id);
 1768     }
 1769     *target = ppix;
 1770     return TRUE;
 1771 }
 1772 
 1773 static Bool
 1774 drmmode_set_target_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix,
 1775                                   PixmapPtr *target)
 1776 {
 1777     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1778     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1779 
 1780     if (drmmode->reverse_prime_offload_mode)
 1781         return drmmode_set_target_scanout_pixmap_gpu(crtc, ppix, target);
 1782     else
 1783         return drmmode_set_target_scanout_pixmap_cpu(crtc, ppix, target);
 1784 }
 1785 
 1786 static Bool
 1787 drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 1788 {
 1789     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1790 
 1791     /* Use DisableSharedPixmapFlipping before switching to single buf */
 1792     if (drmmode_crtc->enable_flipping)
 1793         return FALSE;
 1794 
 1795     return drmmode_set_target_scanout_pixmap(crtc, ppix,
 1796                                              &drmmode_crtc->prime_pixmap);
 1797 }
 1798 
 1799 static void
 1800 drmmode_clear_pixmap(PixmapPtr pixmap)
 1801 {
 1802     ScreenPtr screen = pixmap->drawable.pScreen;
 1803     GCPtr gc;
 1804 
 1805     gc = GetScratchGC(pixmap->drawable.depth, screen);
 1806     if (gc) {
 1807         miClearDrawable(&pixmap->drawable, gc);
 1808         FreeScratchGC(gc);
 1809     }
 1810 }
 1811 
 1812 static void *
 1813 drmmode_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
 1814 {
 1815     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1816     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1817     int ret;
 1818 
 1819     if (!drmmode_create_bo(drmmode, &drmmode_crtc->rotate_bo,
 1820                            width, height, drmmode->kbpp)) {
 1821         xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
 1822                "Couldn't allocate shadow memory for rotated CRTC\n");
 1823         return NULL;
 1824     }
 1825 
 1826     ret = drmmode_bo_import(drmmode, &drmmode_crtc->rotate_bo,
 1827                             &drmmode_crtc->rotate_fb_id);
 1828 
 1829     if (ret) {
 1830         ErrorF("failed to add rotate fb\n");
 1831         drmmode_bo_destroy(drmmode, &drmmode_crtc->rotate_bo);
 1832         return NULL;
 1833     }
 1834 
 1835 #ifdef GLAMOR_HAS_GBM
 1836     if (drmmode->gbm)
 1837         return drmmode_crtc->rotate_bo.gbm;
 1838 #endif
 1839     return drmmode_crtc->rotate_bo.dumb;
 1840 }
 1841 
 1842 static PixmapPtr
 1843 drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int height,
 1844                              int depth, int bitsPerPixel, int devKind,
 1845                              void *pPixData)
 1846 {
 1847     PixmapPtr pixmap;
 1848 
 1849     /* width and height of 0 means don't allocate any pixmap data */
 1850     pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
 1851 
 1852     if (pixmap) {
 1853         if ((*pScreen->ModifyPixmapHeader)(pixmap, width, height, depth,
 1854                                            bitsPerPixel, devKind, pPixData))
 1855             return pixmap;
 1856         (*pScreen->DestroyPixmap)(pixmap);
 1857     }
 1858     return NullPixmap;
 1859 }
 1860 
 1861 static Bool
 1862 drmmode_set_pixmap_bo(drmmode_ptr drmmode, PixmapPtr pixmap, drmmode_bo *bo);
 1863 
 1864 static PixmapPtr
 1865 drmmode_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 1866 {
 1867     ScrnInfoPtr scrn = crtc->scrn;
 1868     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1869     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1870     uint32_t rotate_pitch;
 1871     PixmapPtr rotate_pixmap;
 1872     void *pPixData = NULL;
 1873 
 1874     if (!data) {
 1875         data = drmmode_shadow_allocate(crtc, width, height);
 1876         if (!data) {
 1877             xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 1878                        "Couldn't allocate shadow pixmap for rotated CRTC\n");
 1879             return NULL;
 1880         }
 1881     }
 1882 
 1883     if (!drmmode_bo_has_bo(&drmmode_crtc->rotate_bo)) {
 1884         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 1885                    "Couldn't allocate shadow pixmap for rotated CRTC\n");
 1886         return NULL;
 1887     }
 1888 
 1889     pPixData = drmmode_bo_map(drmmode, &drmmode_crtc->rotate_bo);
 1890     rotate_pitch = drmmode_bo_get_pitch(&drmmode_crtc->rotate_bo),
 1891 
 1892     rotate_pixmap = drmmode_create_pixmap_header(scrn->pScreen,
 1893                                                  width, height,
 1894                                                  scrn->depth,
 1895                                                  drmmode->kbpp,
 1896                                                  rotate_pitch,
 1897                                                  pPixData);
 1898 
 1899     if (rotate_pixmap == NULL) {
 1900         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 1901                    "Couldn't allocate shadow pixmap for rotated CRTC\n");
 1902         return NULL;
 1903     }
 1904 
 1905     drmmode_set_pixmap_bo(drmmode, rotate_pixmap, &drmmode_crtc->rotate_bo);
 1906 
 1907     return rotate_pixmap;
 1908 }
 1909 
 1910 static void
 1911 drmmode_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 1912 {
 1913     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1914     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1915 
 1916     if (rotate_pixmap) {
 1917         rotate_pixmap->drawable.pScreen->DestroyPixmap(rotate_pixmap);
 1918     }
 1919 
 1920     if (data) {
 1921         drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
 1922         drmmode_crtc->rotate_fb_id = 0;
 1923 
 1924         drmmode_bo_destroy(drmmode, &drmmode_crtc->rotate_bo);
 1925         memset(&drmmode_crtc->rotate_bo, 0, sizeof drmmode_crtc->rotate_bo);
 1926     }
 1927 }
 1928 
 1929 static void
 1930 drmmode_crtc_destroy(xf86CrtcPtr crtc)
 1931 {
 1932     drmmode_mode_ptr iterator, next;
 1933     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1934     modesettingPtr ms = modesettingPTR(crtc->scrn);
 1935 
 1936     if (!ms->atomic_modeset)
 1937         return;
 1938 
 1939     drmmode_prop_info_free(drmmode_crtc->props_plane, DRMMODE_PLANE__COUNT);
 1940     xorg_list_for_each_entry_safe(iterator, next, &drmmode_crtc->mode_list, entry) {
 1941         drm_mode_destroy(crtc, iterator);
 1942     }
 1943 }
 1944 
 1945 static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
 1946     .dpms = drmmode_crtc_dpms,
 1947     .set_mode_major = drmmode_set_mode_major,
 1948     .set_cursor_colors = drmmode_set_cursor_colors,
 1949     .set_cursor_position = drmmode_set_cursor_position,
 1950     .show_cursor_check = drmmode_show_cursor,
 1951     .hide_cursor = drmmode_hide_cursor,
 1952     .load_cursor_argb_check = drmmode_load_cursor_argb_check,
 1953 
 1954     .gamma_set = drmmode_crtc_gamma_set,
 1955     .destroy = drmmode_crtc_destroy,
 1956     .set_scanout_pixmap = drmmode_set_scanout_pixmap,
 1957     .shadow_allocate = drmmode_shadow_allocate,
 1958     .shadow_create = drmmode_shadow_create,
 1959     .shadow_destroy = drmmode_shadow_destroy,
 1960 };
 1961 
 1962 static uint32_t
 1963 drmmode_crtc_vblank_pipe(int crtc_id)
 1964 {
 1965     if (crtc_id > 1)
 1966         return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
 1967     else if (crtc_id > 0)
 1968         return DRM_VBLANK_SECONDARY;
 1969     else
 1970         return 0;
 1971 }
 1972 
 1973 static Bool
 1974 is_plane_assigned(ScrnInfoPtr scrn, int plane_id)
 1975 {
 1976     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 1977     int c;
 1978 
 1979     for (c = 0; c < xf86_config->num_crtc; c++) {
 1980         xf86CrtcPtr iter = xf86_config->crtc[c];
 1981         drmmode_crtc_private_ptr drmmode_crtc = iter->driver_private;
 1982         if (drmmode_crtc->plane_id == plane_id)
 1983             return TRUE;
 1984     }
 1985 
 1986     return FALSE;
 1987 }
 1988 
 1989 /**
 1990  * Populates the formats array, and the modifiers of each format for a drm_plane.
 1991  */
 1992 static Bool
 1993 populate_format_modifiers(xf86CrtcPtr crtc, const drmModePlane *kplane,
 1994                           uint32_t blob_id)
 1995 {
 1996     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 1997     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 1998     unsigned i, j;
 1999     drmModePropertyBlobRes *blob;
 2000     struct drm_format_modifier_blob *fmt_mod_blob;
 2001     uint32_t *blob_formats;
 2002     struct drm_format_modifier *blob_modifiers;
 2003 
 2004     if (!blob_id)
 2005         return FALSE;
 2006 
 2007     blob = drmModeGetPropertyBlob(drmmode->fd, blob_id);
 2008     if (!blob)
 2009         return FALSE;
 2010 
 2011     fmt_mod_blob = blob->data;
 2012     blob_formats = formats_ptr(fmt_mod_blob);
 2013     blob_modifiers = modifiers_ptr(fmt_mod_blob);
 2014 
 2015     assert(drmmode_crtc->num_formats == fmt_mod_blob->count_formats);
 2016 
 2017     for (i = 0; i < fmt_mod_blob->count_formats; i++) {
 2018         uint32_t num_modifiers = 0;
 2019         uint64_t *modifiers = NULL;
 2020         uint64_t *tmp;
 2021         for (j = 0; j < fmt_mod_blob->count_modifiers; j++) {
 2022             struct drm_format_modifier *mod = &blob_modifiers[j];
 2023 
 2024             if ((i < mod->offset) || (i > mod->offset + 63))
 2025                 continue;
 2026             if (!(mod->formats & (1 << (i - mod->offset))))
 2027                 continue;
 2028 
 2029             num_modifiers++;
 2030             tmp = realloc(modifiers, num_modifiers * sizeof(modifiers[0]));
 2031             if (!tmp) {
 2032                 free(modifiers);
 2033                 drmModeFreePropertyBlob(blob);
 2034                 return FALSE;
 2035             }
 2036             modifiers = tmp;
 2037             modifiers[num_modifiers - 1] = mod->modifier;
 2038         }
 2039 
 2040         drmmode_crtc->formats[i].format = blob_formats[i];
 2041         drmmode_crtc->formats[i].modifiers = modifiers;
 2042         drmmode_crtc->formats[i].num_modifiers = num_modifiers;
 2043     }
 2044 
 2045     drmModeFreePropertyBlob(blob);
 2046 
 2047     return TRUE;
 2048 }
 2049 
 2050 static void
 2051 drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
 2052 {
 2053     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 2054     drmmode_ptr drmmode = drmmode_crtc->drmmode;
 2055     drmModePlaneRes *kplane_res;
 2056     drmModePlane *kplane, *best_kplane = NULL;
 2057     drmModeObjectProperties *props;
 2058     uint32_t i, type, blob_id;
 2059     int current_crtc, best_plane = 0;
 2060 
 2061     static drmmode_prop_enum_info_rec plane_type_enums[] = {
 2062         [DRMMODE_PLANE_TYPE_PRIMARY] = {
 2063             .name = "Primary",
 2064         },
 2065         [DRMMODE_PLANE_TYPE_OVERLAY] = {
 2066             .name = "Overlay",
 2067         },
 2068         [DRMMODE_PLANE_TYPE_CURSOR] = {
 2069             .name = "Cursor",
 2070         },
 2071     };
 2072     static const drmmode_prop_info_rec plane_props[] = {
 2073         [DRMMODE_PLANE_TYPE] = {
 2074             .name = "type",
 2075             .enum_values = plane_type_enums,
 2076             .num_enum_values = DRMMODE_PLANE_TYPE__COUNT,
 2077         },
 2078         [DRMMODE_PLANE_FB_ID] = { .name = "FB_ID", },
 2079         [DRMMODE_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
 2080         [DRMMODE_PLANE_IN_FORMATS] = { .name = "IN_FORMATS", },
 2081         [DRMMODE_PLANE_SRC_X] = { .name = "SRC_X", },
 2082         [DRMMODE_PLANE_SRC_Y] = { .name = "SRC_Y", },
 2083         [DRMMODE_PLANE_SRC_W] = { .name = "SRC_W", },
 2084         [DRMMODE_PLANE_SRC_H] = { .name = "SRC_H", },
 2085         [DRMMODE_PLANE_CRTC_X] = { .name = "CRTC_X", },
 2086         [DRMMODE_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
 2087         [DRMMODE_PLANE_CRTC_W] = { .name = "CRTC_W", },
 2088         [DRMMODE_PLANE_CRTC_H] = { .name = "CRTC_H", },
 2089     };
 2090     drmmode_prop_info_rec tmp_props[DRMMODE_PLANE__COUNT];
 2091 
 2092     if (!drmmode_prop_info_copy(tmp_props, plane_props, DRMMODE_PLANE__COUNT, 0)) {
 2093         xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
 2094                    "failed to copy plane property info\n");
 2095         drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
 2096         return;
 2097     }
 2098 
 2099     kplane_res = drmModeGetPlaneResources(drmmode->fd);
 2100     if (!kplane_res) {
 2101         xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
 2102                    "failed to get plane resources: %s\n", strerror(errno));
 2103         drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
 2104         return;
 2105     }
 2106 
 2107     for (i = 0; i < kplane_res->count_planes; i++) {
 2108         int plane_id;
 2109 
 2110         kplane = drmModeGetPlane(drmmode->fd, kplane_res->planes[i]);
 2111         if (!kplane)
 2112             continue;
 2113 
 2114         if (!(kplane->possible_crtcs & (1 << num)) ||
 2115             is_plane_assigned(drmmode->scrn, kplane->plane_id)) {
 2116             drmModeFreePlane(kplane);
 2117             continue;
 2118         }
 2119 
 2120         plane_id = kplane->plane_id;
 2121 
 2122         props = drmModeObjectGetProperties(drmmode->fd, plane_id,
 2123                                            DRM_MODE_OBJECT_PLANE);
 2124         if (!props) {
 2125             xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
 2126                     "couldn't get plane properties\n");
 2127             drmModeFreePlane(kplane);
 2128             continue;
 2129         }
 2130 
 2131         drmmode_prop_info_update(drmmode, tmp_props, DRMMODE_PLANE__COUNT, props);
 2132 
 2133         /* Only primary planes are important for atomic page-flipping */
 2134         type = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_TYPE],
 2135                                       props, DRMMODE_PLANE_TYPE__COUNT);
 2136         if (type != DRMMODE_PLANE_TYPE_PRIMARY) {
 2137             drmModeFreePlane(kplane);
 2138             drmModeFreeObjectProperties(props);
 2139             continue;
 2140         }
 2141 
 2142         /* Check if plane is already on this CRTC */
 2143         current_crtc = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_CRTC_ID],
 2144                                               props, 0);
 2145         if (current_crtc == drmmode_crtc->mode_crtc->crtc_id) {
 2146             if (best_plane) {
 2147                 drmModeFreePlane(best_kplane);
 2148                 drmmode_prop_info_free(drmmode_crtc->props_plane, DRMMODE_PLANE__COUNT);
 2149             }
 2150             best_plane = plane_id;
 2151             best_kplane = kplane;
 2152             blob_id = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_IN_FORMATS],
 2153                                              props, 0);
 2154             drmmode_prop_info_copy(drmmode_crtc->props_plane, tmp_props,
 2155                                    DRMMODE_PLANE__COUNT, 1);
 2156             drmModeFreeObjectProperties(props);
 2157             break;
 2158         }
 2159 
 2160         if (!best_plane) {
 2161             best_plane = plane_id;
 2162             best_kplane = kplane;
 2163             blob_id = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_IN_FORMATS],
 2164                                              props, 0);
 2165             drmmode_prop_info_copy(drmmode_crtc->props_plane, tmp_props,
 2166                                    DRMMODE_PLANE__COUNT, 1);
 2167         } else {
 2168             drmModeFreePlane(kplane);
 2169         }
 2170 
 2171         drmModeFreeObjectProperties(props);
 2172     }
 2173 
 2174     drmmode_crtc->plane_id = best_plane;
 2175     if (best_kplane) {
 2176         drmmode_crtc->num_formats = best_kplane->count_formats;
 2177         drmmode_crtc->formats = calloc(sizeof(drmmode_format_rec),
 2178                                        best_kplane->count_formats);
 2179         if (!populate_format_modifiers(crtc, best_kplane, blob_id)) {
 2180             for (i = 0; i < best_kplane->count_formats; i++)
 2181                 drmmode_crtc->formats[i].format = best_kplane->formats[i];
 2182         }
 2183         drmModeFreePlane(best_kplane);
 2184     }
 2185 
 2186     drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
 2187     drmModeFreePlaneResources(kplane_res);
 2188 }
 2189 
 2190 static unsigned int
 2191 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
 2192 {
 2193     xf86CrtcPtr crtc;
 2194     drmmode_crtc_private_ptr drmmode_crtc;
 2195     modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
 2196     modesettingPtr ms = modesettingPTR(pScrn);
 2197     drmModeObjectPropertiesPtr props;
 2198     static const drmmode_prop_info_rec crtc_props[] = {
 2199         [DRMMODE_CRTC_ACTIVE] = { .name = "ACTIVE" },
 2200         [DRMMODE_CRTC_MODE_ID] = { .name = "MODE_ID" },
 2201     };
 2202 
 2203     crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
 2204     if (crtc == NULL)
 2205         return 0;
 2206     drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
 2207     crtc->driver_private = drmmode_crtc;
 2208     drmmode_crtc->mode_crtc =
 2209         drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
 2210     drmmode_crtc->drmmode = drmmode;
 2211     drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num);
 2212     xorg_list_init(&drmmode_crtc->mode_list);
 2213 
 2214     if (ms->atomic_modeset) {
 2215         props = drmModeObjectGetProperties(drmmode->fd, mode_res->crtcs[num],
 2216                                            DRM_MODE_OBJECT_CRTC);
 2217         if (!props || !drmmode_prop_info_copy(drmmode_crtc->props, crtc_props,
 2218                                               DRMMODE_CRTC__COUNT, 0)) {
 2219             xf86CrtcDestroy(crtc);
 2220             return 0;
 2221         }
 2222 
 2223         drmmode_prop_info_update(drmmode, drmmode_crtc->props,
 2224                                  DRMMODE_CRTC__COUNT, props);
 2225         drmModeFreeObjectProperties(props);
 2226         drmmode_crtc_create_planes(crtc, num);
 2227     }
 2228 
 2229     /* Hide any cursors which may be active from previous users */
 2230     drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0);
 2231 
 2232     /* Mark num'th crtc as in use on this device. */
 2233     ms_ent->assigned_crtcs |= (1 << num);
 2234     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
 2235                    "Allocated crtc nr. %d to this screen.\n", num);
 2236 
 2237     return 1;
 2238 }
 2239 
 2240 /*
 2241  * Update all of the property values for an output
 2242  */
 2243 static void
 2244 drmmode_output_update_properties(xf86OutputPtr output)
 2245 {
 2246     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2247     int i, j, k;
 2248     int err;
 2249     drmModeConnectorPtr koutput;
 2250 
 2251     /* Use the most recently fetched values from the kernel */
 2252     koutput = drmmode_output->mode_output;
 2253 
 2254     if (!koutput)
 2255         return;
 2256 
 2257     for (i = 0; i < drmmode_output->num_props; i++) {
 2258         drmmode_prop_ptr p = &drmmode_output->props[i];
 2259 
 2260         for (j = 0; koutput && j < koutput->count_props; j++) {
 2261             if (koutput->props[j] == p->mode_prop->prop_id) {
 2262 
 2263                 /* Check to see if the property value has changed */
 2264                 if (koutput->prop_values[j] != p->value) {
 2265 
 2266                     p->value = koutput->prop_values[j];
 2267 
 2268                     if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
 2269                         INT32 value = p->value;
 2270 
 2271                         err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
 2272                                                      XA_INTEGER, 32, PropModeReplace, 1,
 2273                                                      &value, FALSE, TRUE);
 2274 
 2275                         if (err != 0) {
 2276                             xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2277                                        "RRChangeOutputProperty error, %d\n", err);
 2278                         }
 2279                     }
 2280                     else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
 2281                         for (k = 0; k < p->mode_prop->count_enums; k++)
 2282                             if (p->mode_prop->enums[k].value == p->value)
 2283                                 break;
 2284                         if (k < p->mode_prop->count_enums) {
 2285                             err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
 2286                                                          XA_ATOM, 32, PropModeReplace, 1,
 2287                                                          &p->atoms[k + 1], FALSE, TRUE);
 2288                             if (err != 0) {
 2289                                 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2290                                            "RRChangeOutputProperty error, %d\n", err);
 2291                             }
 2292                         }
 2293                     }
 2294                 }
 2295                 break;
 2296             }
 2297         }
 2298     }
 2299 }
 2300 
 2301 static xf86OutputStatus
 2302 drmmode_output_detect(xf86OutputPtr output)
 2303 {
 2304     /* go to the hw and retrieve a new output struct */
 2305     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2306     drmmode_ptr drmmode = drmmode_output->drmmode;
 2307     xf86OutputStatus status;
 2308 
 2309     if (drmmode_output->output_id == -1)
 2310         return XF86OutputStatusDisconnected;
 2311 
 2312     drmModeFreeConnector(drmmode_output->mode_output);
 2313 
 2314     drmmode_output->mode_output =
 2315         drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
 2316 
 2317     if (!drmmode_output->mode_output) {
 2318         drmmode_output->output_id = -1;
 2319         return XF86OutputStatusDisconnected;
 2320     }
 2321 
 2322     drmmode_output_update_properties(output);
 2323 
 2324     switch (drmmode_output->mode_output->connection) {
 2325     case DRM_MODE_CONNECTED:
 2326         status = XF86OutputStatusConnected;
 2327         break;
 2328     case DRM_MODE_DISCONNECTED:
 2329         status = XF86OutputStatusDisconnected;
 2330         break;
 2331     default:
 2332     case DRM_MODE_UNKNOWNCONNECTION:
 2333         status = XF86OutputStatusUnknown;
 2334         break;
 2335     }
 2336     return status;
 2337 }
 2338 
 2339 static Bool
 2340 drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
 2341 {
 2342     return MODE_OK;
 2343 }
 2344 
 2345 static int
 2346 koutput_get_prop_idx(int fd, drmModeConnectorPtr koutput,
 2347         int type, const char *name)
 2348 {
 2349     int idx = -1;
 2350 
 2351     for (int i = 0; i < koutput->count_props; i++) {
 2352         drmModePropertyPtr prop = drmModeGetProperty(fd, koutput->props[i]);
 2353 
 2354         if (!prop)
 2355             continue;
 2356 
 2357         if (drm_property_type_is(prop, type) && !strcmp(prop->name, name))
 2358             idx = i;
 2359 
 2360         drmModeFreeProperty(prop);
 2361 
 2362         if (idx > -1)
 2363             break;
 2364     }
 2365 
 2366     return idx;
 2367 }
 2368 
 2369 static int
 2370 koutput_get_prop_id(int fd, drmModeConnectorPtr koutput,
 2371         int type, const char *name)
 2372 {
 2373     int idx = koutput_get_prop_idx(fd, koutput, type, name);
 2374 
 2375     return (idx > -1) ? koutput->props[idx] : -1;
 2376 }
 2377 
 2378 static drmModePropertyBlobPtr
 2379 koutput_get_prop_blob(int fd, drmModeConnectorPtr koutput, const char *name)
 2380 {
 2381     drmModePropertyBlobPtr blob = NULL;
 2382     int idx = koutput_get_prop_idx(fd, koutput, DRM_MODE_PROP_BLOB, name);
 2383 
 2384     if (idx > -1)
 2385         blob = drmModeGetPropertyBlob(fd, koutput->prop_values[idx]);
 2386 
 2387     return blob;
 2388 }
 2389 
 2390 static void
 2391 drmmode_output_attach_tile(xf86OutputPtr output)
 2392 {
 2393     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2394     drmModeConnectorPtr koutput = drmmode_output->mode_output;
 2395     drmmode_ptr drmmode = drmmode_output->drmmode;
 2396     struct xf86CrtcTileInfo tile_info, *set = NULL;
 2397 
 2398     if (!koutput) {
 2399         xf86OutputSetTile(output, NULL);
 2400         return;
 2401     }
 2402 
 2403     drmModeFreePropertyBlob(drmmode_output->tile_blob);
 2404 
 2405     /* look for a TILE property */
 2406     drmmode_output->tile_blob =
 2407         koutput_get_prop_blob(drmmode->fd, koutput, "TILE");
 2408 
 2409     if (drmmode_output->tile_blob) {
 2410         if (xf86OutputParseKMSTile(drmmode_output->tile_blob->data, drmmode_output->tile_blob->length, &tile_info) == TRUE)
 2411             set = &tile_info;
 2412     }
 2413     xf86OutputSetTile(output, set);
 2414 }
 2415 
 2416 static Bool
 2417 has_panel_fitter(xf86OutputPtr output)
 2418 {
 2419     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2420     drmModeConnectorPtr koutput = drmmode_output->mode_output;
 2421     drmmode_ptr drmmode = drmmode_output->drmmode;
 2422     int idx;
 2423 
 2424     /* Presume that if the output supports scaling, then we have a
 2425      * panel fitter capable of adjust any mode to suit.
 2426      */
 2427     idx = koutput_get_prop_idx(drmmode->fd, koutput,
 2428             DRM_MODE_PROP_ENUM, "scaling mode");
 2429 
 2430     return (idx > -1);
 2431 }
 2432 
 2433 static DisplayModePtr
 2434 drmmode_output_add_gtf_modes(xf86OutputPtr output, DisplayModePtr Modes)
 2435 {
 2436     xf86MonPtr mon = output->MonInfo;
 2437     DisplayModePtr i, m, preferred = NULL;
 2438     int max_x = 0, max_y = 0;
 2439     float max_vrefresh = 0.0;
 2440 
 2441     if (mon && GTF_SUPPORTED(mon->features.msc))
 2442         return Modes;
 2443 
 2444     if (!has_panel_fitter(output))
 2445         return Modes;
 2446 
 2447     for (m = Modes; m; m = m->next) {
 2448         if (m->type & M_T_PREFERRED)
 2449             preferred = m;
 2450         max_x = max(max_x, m->HDisplay);
 2451         max_y = max(max_y, m->VDisplay);
 2452         max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
 2453     }
 2454 
 2455     max_vrefresh = max(max_vrefresh, 60.0);
 2456     max_vrefresh *= (1 + SYNC_TOLERANCE);
 2457 
 2458     m = xf86GetDefaultModes();
 2459     xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
 2460 
 2461     for (i = m; i; i = i->next) {
 2462         if (xf86ModeVRefresh(i) > max_vrefresh)
 2463             i->status = MODE_VSYNC;
 2464         if (preferred &&
 2465             i->HDisplay >= preferred->HDisplay &&
 2466             i->VDisplay >= preferred->VDisplay &&
 2467             xf86ModeVRefresh(i) >= xf86ModeVRefresh(preferred))
 2468             i->status = MODE_VSYNC;
 2469     }
 2470 
 2471     xf86PruneInvalidModes(output->scrn, &m, FALSE);
 2472 
 2473     return xf86ModesAdd(Modes, m);
 2474 }
 2475 
 2476 static DisplayModePtr
 2477 drmmode_output_get_modes(xf86OutputPtr output)
 2478 {
 2479     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2480     drmModeConnectorPtr koutput = drmmode_output->mode_output;
 2481     drmmode_ptr drmmode = drmmode_output->drmmode;
 2482     int i;
 2483     DisplayModePtr Modes = NULL, Mode;
 2484     xf86MonPtr mon = NULL;
 2485 
 2486     if (!koutput)
 2487         return NULL;
 2488 
 2489     drmModeFreePropertyBlob(drmmode_output->edid_blob);
 2490 
 2491     /* look for an EDID property */
 2492     drmmode_output->edid_blob =
 2493         koutput_get_prop_blob(drmmode->fd, koutput, "EDID");
 2494 
 2495     if (drmmode_output->edid_blob) {
 2496         mon = xf86InterpretEDID(output->scrn->scrnIndex,
 2497                                 drmmode_output->edid_blob->data);
 2498         if (mon && drmmode_output->edid_blob->length > 128)
 2499             mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
 2500     }
 2501     xf86OutputSetEDID(output, mon);
 2502 
 2503     drmmode_output_attach_tile(output);
 2504 
 2505     /* modes should already be available */
 2506     for (i = 0; i < koutput->count_modes; i++) {
 2507         Mode = xnfalloc(sizeof(DisplayModeRec));
 2508 
 2509         drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
 2510         Modes = xf86ModesAdd(Modes, Mode);
 2511 
 2512     }
 2513 
 2514     return drmmode_output_add_gtf_modes(output, Modes);
 2515 }
 2516 
 2517 static void
 2518 drmmode_output_destroy(xf86OutputPtr output)
 2519 {
 2520     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2521     int i;
 2522 
 2523     drmModeFreePropertyBlob(drmmode_output->edid_blob);
 2524     drmModeFreePropertyBlob(drmmode_output->tile_blob);
 2525 
 2526     for (i = 0; i < drmmode_output->num_props; i++) {
 2527         drmModeFreeProperty(drmmode_output->props[i].mode_prop);
 2528         free(drmmode_output->props[i].atoms);
 2529     }
 2530     free(drmmode_output->props);
 2531     if (drmmode_output->mode_output) {
 2532         for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
 2533             drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
 2534         }
 2535         drmModeFreeConnector(drmmode_output->mode_output);
 2536     }
 2537     free(drmmode_output->mode_encoders);
 2538     free(drmmode_output);
 2539     output->driver_private = NULL;
 2540 }
 2541 
 2542 static void
 2543 drmmode_output_dpms(xf86OutputPtr output, int mode)
 2544 {
 2545     modesettingPtr ms = modesettingPTR(output->scrn);
 2546     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2547     drmmode_ptr drmmode = drmmode_output->drmmode;
 2548     xf86CrtcPtr crtc = output->crtc;
 2549     drmModeConnectorPtr koutput = drmmode_output->mode_output;
 2550 
 2551     if (!koutput)
 2552         return;
 2553 
 2554     /* XXX Check if DPMS mode is already the right one */
 2555 
 2556     drmmode_output->dpms = mode;
 2557 
 2558     if (ms->atomic_modeset) {
 2559         if (mode != DPMSModeOn && !ms->pending_modeset)
 2560             drmmode_output_disable(output);
 2561     } else {
 2562         drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
 2563                                     drmmode_output->dpms_enum_id, mode);
 2564     }
 2565 
 2566     if (crtc) {
 2567         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 2568 
 2569         if (mode == DPMSModeOn) {
 2570             if (drmmode_crtc->need_modeset)
 2571                 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
 2572                                        crtc->x, crtc->y);
 2573 
 2574             if (drmmode_crtc->enable_flipping)
 2575                 drmmode_InitSharedPixmapFlipping(crtc, drmmode_crtc->drmmode);
 2576         } else {
 2577             if (drmmode_crtc->enable_flipping)
 2578                 drmmode_FiniSharedPixmapFlipping(crtc, drmmode_crtc->drmmode);
 2579         }
 2580     }
 2581 
 2582     return;
 2583 }
 2584 
 2585 static Bool
 2586 drmmode_property_ignore(drmModePropertyPtr prop)
 2587 {
 2588     if (!prop)
 2589         return TRUE;
 2590     /* ignore blob prop */
 2591     if (prop->flags & DRM_MODE_PROP_BLOB)
 2592         return TRUE;
 2593     /* ignore standard property */
 2594     if (!strcmp(prop->name, "EDID") || !strcmp(prop->name, "DPMS") ||
 2595         !strcmp(prop->name, "CRTC_ID"))
 2596         return TRUE;
 2597 
 2598     return FALSE;
 2599 }
 2600 
 2601 static void
 2602 drmmode_output_create_resources(xf86OutputPtr output)
 2603 {
 2604     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2605     drmModeConnectorPtr mode_output = drmmode_output->mode_output;
 2606     drmmode_ptr drmmode = drmmode_output->drmmode;
 2607     drmModePropertyPtr drmmode_prop;
 2608     int i, j, err;
 2609 
 2610     drmmode_output->props =
 2611         calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
 2612     if (!drmmode_output->props)
 2613         return;
 2614 
 2615     drmmode_output->num_props = 0;
 2616     for (i = 0, j = 0; i < mode_output->count_props; i++) {
 2617         drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
 2618         if (drmmode_property_ignore(drmmode_prop)) {
 2619             drmModeFreeProperty(drmmode_prop);
 2620             continue;
 2621         }
 2622         drmmode_output->props[j].mode_prop = drmmode_prop;
 2623         drmmode_output->props[j].value = mode_output->prop_values[i];
 2624         drmmode_output->num_props++;
 2625         j++;
 2626     }
 2627 
 2628     /* Create CONNECTOR_ID property */
 2629     {
 2630         Atom    name = MakeAtom("CONNECTOR_ID", 12, TRUE);
 2631         INT32   value = mode_output->connector_id;
 2632 
 2633         if (name != BAD_RESOURCE) {
 2634             err = RRConfigureOutputProperty(output->randr_output, name,
 2635                                             FALSE, FALSE, TRUE,
 2636                                             1, &value);
 2637             if (err != 0) {
 2638                 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2639                            "RRConfigureOutputProperty error, %d\n", err);
 2640             }
 2641             err = RRChangeOutputProperty(output->randr_output, name,
 2642                                          XA_INTEGER, 32, PropModeReplace, 1,
 2643                                          &value, FALSE, FALSE);
 2644             if (err != 0) {
 2645                 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2646                            "RRChangeOutputProperty error, %d\n", err);
 2647             }
 2648         }
 2649     }
 2650 
 2651     for (i = 0; i < drmmode_output->num_props; i++) {
 2652         drmmode_prop_ptr p = &drmmode_output->props[i];
 2653 
 2654         drmmode_prop = p->mode_prop;
 2655 
 2656         if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
 2657             INT32 prop_range[2];
 2658             INT32 value = p->value;
 2659 
 2660             p->num_atoms = 1;
 2661             p->atoms = calloc(p->num_atoms, sizeof(Atom));
 2662             if (!p->atoms)
 2663                 continue;
 2664             p->atoms[0] =
 2665                 MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
 2666             prop_range[0] = drmmode_prop->values[0];
 2667             prop_range[1] = drmmode_prop->values[1];
 2668             err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
 2669                                             FALSE, TRUE,
 2670                                             drmmode_prop->
 2671                                             flags & DRM_MODE_PROP_IMMUTABLE ?
 2672                                             TRUE : FALSE, 2, prop_range);
 2673             if (err != 0) {
 2674                 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2675                            "RRConfigureOutputProperty error, %d\n", err);
 2676             }
 2677             err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
 2678                                          XA_INTEGER, 32, PropModeReplace, 1,
 2679                                          &value, FALSE, TRUE);
 2680             if (err != 0) {
 2681                 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2682                            "RRChangeOutputProperty error, %d\n", err);
 2683             }
 2684         }
 2685         else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
 2686             p->num_atoms = drmmode_prop->count_enums + 1;
 2687             p->atoms = calloc(p->num_atoms, sizeof(Atom));
 2688             if (!p->atoms)
 2689                 continue;
 2690             p->atoms[0] =
 2691                 MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
 2692             for (j = 1; j <= drmmode_prop->count_enums; j++) {
 2693                 struct drm_mode_property_enum *e = &drmmode_prop->enums[j - 1];
 2694 
 2695                 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
 2696             }
 2697             err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
 2698                                             FALSE, FALSE,
 2699                                             drmmode_prop->
 2700                                             flags & DRM_MODE_PROP_IMMUTABLE ?
 2701                                             TRUE : FALSE, p->num_atoms - 1,
 2702                                             (INT32 *) &p->atoms[1]);
 2703             if (err != 0) {
 2704                 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2705                            "RRConfigureOutputProperty error, %d\n", err);
 2706             }
 2707             for (j = 0; j < drmmode_prop->count_enums; j++)
 2708                 if (drmmode_prop->enums[j].value == p->value)
 2709                     break;
 2710             /* there's always a matching value */
 2711             err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
 2712                                          XA_ATOM, 32, PropModeReplace, 1,
 2713                                          &p->atoms[j + 1], FALSE, TRUE);
 2714             if (err != 0) {
 2715                 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 2716                            "RRChangeOutputProperty error, %d\n", err);
 2717             }
 2718         }
 2719     }
 2720 }
 2721 
 2722 static Bool
 2723 drmmode_output_set_property(xf86OutputPtr output, Atom property,
 2724                             RRPropertyValuePtr value)
 2725 {
 2726     drmmode_output_private_ptr drmmode_output = output->driver_private;
 2727     drmmode_ptr drmmode = drmmode_output->drmmode;
 2728     int i;
 2729 
 2730     for (i = 0; i < drmmode_output->num_props; i++) {
 2731         drmmode_prop_ptr p = &drmmode_output->props[i];
 2732 
 2733         if (p->atoms[0] != property)
 2734             continue;
 2735 
 2736         if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
 2737             uint32_t val;
 2738 
 2739             if (value->type != XA_INTEGER || value->format != 32 ||
 2740                 value->size != 1)
 2741                 return FALSE;
 2742             val = *(uint32_t *) value->data;
 2743 
 2744             drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
 2745                                         p->mode_prop->prop_id, (uint64_t) val);
 2746             return TRUE;
 2747         }
 2748         else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
 2749             Atom atom;
 2750             const char *name;
 2751             int j;
 2752 
 2753             if (value->type != XA_ATOM || value->format != 32 ||
 2754                 value->size != 1)
 2755                 return FALSE;
 2756             memcpy(&atom, value->data, 4);
 2757             if (!(name = NameForAtom(atom)))
 2758                 return FALSE;
 2759 
 2760             /* search for matching name string, then set its value down */
 2761             for (j = 0; j < p->mode_prop->count_enums; j++) {
 2762                 if (!strcmp(p->mode_prop->enums[j].name, name)) {
 2763                     drmModeConnectorSetProperty(drmmode->fd,
 2764                                                 drmmode_output->output_id,
 2765                                                 p->mode_prop->prop_id,
 2766                                                 p->mode_prop->enums[j].value);
 2767                     return TRUE;
 2768                 }
 2769             }
 2770         }
 2771     }
 2772 
 2773     return TRUE;
 2774 }
 2775 
 2776 static Bool
 2777 drmmode_output_get_property(xf86OutputPtr output, Atom property)
 2778 {
 2779     return TRUE;
 2780 }
 2781 
 2782 static const xf86OutputFuncsRec drmmode_output_funcs = {
 2783     .dpms = drmmode_output_dpms,
 2784     .create_resources = drmmode_output_create_resources,
 2785     .set_property = drmmode_output_set_property,
 2786     .get_property = drmmode_output_get_property,
 2787     .detect = drmmode_output_detect,
 2788     .mode_valid = drmmode_output_mode_valid,
 2789 
 2790     .get_modes = drmmode_output_get_modes,
 2791     .destroy = drmmode_output_destroy
 2792 };
 2793 
 2794 static int subpixel_conv_table[7] = {
 2795     0,
 2796     SubPixelUnknown,
 2797     SubPixelHorizontalRGB,
 2798     SubPixelHorizontalBGR,
 2799     SubPixelVerticalRGB,
 2800     SubPixelVerticalBGR,
 2801     SubPixelNone
 2802 };
 2803 
 2804 static const char *const output_names[] = {
 2805     "None",
 2806     "VGA",
 2807     "DVI-I",
 2808     "DVI-D",
 2809     "DVI-A",
 2810     "Composite",
 2811     "SVIDEO",
 2812     "LVDS",
 2813     "Component",
 2814     "DIN",
 2815     "DP",
 2816     "HDMI",
 2817     "HDMI-B",
 2818     "TV",
 2819     "eDP",
 2820     "Virtual",
 2821     "DSI",
 2822     "DPI",
 2823 };
 2824 
 2825 static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id)
 2826 {
 2827     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 2828     int i;
 2829     for (i = 0; i < xf86_config->num_output; i++) {
 2830         xf86OutputPtr output = xf86_config->output[i];
 2831         drmmode_output_private_ptr drmmode_output;
 2832 
 2833         drmmode_output = output->driver_private;
 2834         if (drmmode_output->output_id == id)
 2835             return output;
 2836     }
 2837     return NULL;
 2838 }
 2839 
 2840 static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path)
 2841 {
 2842     char *conn;
 2843     char conn_id[5];
 2844     int id, len;
 2845     char *blob_data;
 2846 
 2847     if (!path_blob)
 2848         return -1;
 2849 
 2850     blob_data = path_blob->data;
 2851     /* we only handle MST paths for now */
 2852     if (strncmp(blob_data, "mst:", 4))
 2853         return -1;
 2854 
 2855     conn = strchr(blob_data + 4, '-');
 2856     if (!conn)
 2857         return -1;
 2858     len = conn - (blob_data + 4);
 2859     if (len + 1> 5)
 2860         return -1;
 2861     memcpy(conn_id, blob_data + 4, len);
 2862     conn_id[len] = '\0';
 2863     id = strtoul(conn_id, NULL, 10);
 2864 
 2865     *conn_base_id = id;
 2866 
 2867     *path = conn + 1;
 2868     return 0;
 2869 }
 2870 
 2871 static void
 2872 drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
 2873             drmModePropertyBlobPtr path_blob)
 2874 {
 2875     int ret;
 2876     char *extra_path;
 2877     int conn_id;
 2878     xf86OutputPtr output;
 2879 
 2880     ret = parse_path_blob(path_blob, &conn_id, &extra_path);
 2881     if (ret == -1)
 2882         goto fallback;
 2883 
 2884     output = find_output(pScrn, conn_id);
 2885     if (!output)
 2886         goto fallback;
 2887 
 2888     snprintf(name, 32, "%s-%s", output->name, extra_path);
 2889     return;
 2890 
 2891  fallback:
 2892     if (koutput->connector_type >= ARRAY_SIZE(output_names))
 2893         snprintf(name, 32, "Unknown%d-%d", koutput->connector_type, koutput->connector_type_id);
 2894     else if (pScrn->is_gpu)
 2895         snprintf(name, 32, "%s-%d-%d", output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1, koutput->connector_type_id);
 2896     else
 2897         snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id);
 2898 }
 2899 
 2900 static unsigned int
 2901 drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic, int crtcshift)
 2902 {
 2903     xf86OutputPtr output;
 2904     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 2905     modesettingPtr ms = modesettingPTR(pScrn);
 2906     drmModeConnectorPtr koutput;
 2907     drmModeEncoderPtr *kencoders = NULL;
 2908     drmmode_output_private_ptr drmmode_output;
 2909     char name[32];
 2910     int i;
 2911     Bool nonDesktop = FALSE;
 2912     drmModePropertyBlobPtr path_blob = NULL;
 2913     const char *s;
 2914     drmModeObjectPropertiesPtr props;
 2915     static const drmmode_prop_info_rec connector_props[] = {
 2916         [DRMMODE_CONNECTOR_CRTC_ID] = { .name = "CRTC_ID", },
 2917     };
 2918 
 2919     koutput =
 2920         drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
 2921     if (!koutput)
 2922         return 0;
 2923 
 2924     path_blob = koutput_get_prop_blob(drmmode->fd, koutput, "PATH");
 2925     i = koutput_get_prop_idx(drmmode->fd, koutput, DRM_MODE_PROP_RANGE, RR_PROPERTY_NON_DESKTOP);
 2926     if (i >= 0)
 2927         nonDesktop = koutput->prop_values[i] != 0;
 2928 
 2929     drmmode_create_name(pScrn, koutput, name, path_blob);
 2930 
 2931     if (path_blob)
 2932         drmModeFreePropertyBlob(path_blob);
 2933 
 2934     if (path_blob && dynamic) {
 2935         /* see if we have an output with this name already
 2936            and hook stuff up */
 2937         for (i = 0; i < xf86_config->num_output; i++) {
 2938             output = xf86_config->output[i];
 2939 
 2940             if (strncmp(output->name, name, 32))
 2941                 continue;
 2942 
 2943             drmmode_output = output->driver_private;
 2944             drmmode_output->output_id = mode_res->connectors[num];
 2945             drmmode_output->mode_output = koutput;
 2946             output->non_desktop = nonDesktop;
 2947             return 1;
 2948         }
 2949     }
 2950 
 2951     kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
 2952     if (!kencoders) {
 2953         goto out_free_encoders;
 2954     }
 2955 
 2956     for (i = 0; i < koutput->count_encoders; i++) {
 2957         kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
 2958         if (!kencoders[i]) {
 2959             goto out_free_encoders;
 2960         }
 2961     }
 2962 
 2963     if (xf86IsEntityShared(pScrn->entityList[0])) {
 2964         if ((s = xf86GetOptValString(drmmode->Options, OPTION_ZAPHOD_HEADS))) {
 2965             if (!drmmode_zaphod_string_matches(pScrn, s, name))
 2966                 goto out_free_encoders;
 2967         } else {
 2968             if (!drmmode->is_secondary && (num != 0))
 2969                 goto out_free_encoders;
 2970             else if (drmmode->is_secondary && (num != 1))
 2971                 goto out_free_encoders;
 2972         }
 2973     }
 2974 
 2975     output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
 2976     if (!output) {
 2977         goto out_free_encoders;
 2978     }
 2979 
 2980     drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
 2981     if (!drmmode_output) {
 2982         xf86OutputDestroy(output);
 2983         goto out_free_encoders;
 2984     }
 2985 
 2986     drmmode_output->output_id = mode_res->connectors[num];
 2987     drmmode_output->mode_output = koutput;
 2988     drmmode_output->mode_encoders = kencoders;
 2989     drmmode_output->drmmode = drmmode;
 2990     output->mm_width = koutput->mmWidth;
 2991     output->mm_height = koutput->mmHeight;
 2992 
 2993     output->subpixel_order = subpixel_conv_table[koutput->subpixel];
 2994     output->interlaceAllowed = TRUE;
 2995     output->doubleScanAllowed = TRUE;
 2996     output->driver_private = drmmode_output;
 2997     output->non_desktop = nonDesktop;
 2998 
 2999     output->possible_crtcs = 0x7f;
 3000     for (i = 0; i < koutput->count_encoders; i++) {
 3001         output->possible_crtcs &= kencoders[i]->possible_crtcs >> crtcshift;
 3002     }
 3003     /* work out the possible clones later */
 3004     output->possible_clones = 0;
 3005 
 3006     if (ms->atomic_modeset) {
 3007         if (!drmmode_prop_info_copy(drmmode_output->props_connector,
 3008                                     connector_props, DRMMODE_CONNECTOR__COUNT,
 3009                                     0)) {
 3010             goto out_free_encoders;
 3011         }
 3012         props = drmModeObjectGetProperties(drmmode->fd,
 3013                                            drmmode_output->output_id,
 3014                                            DRM_MODE_OBJECT_CONNECTOR);
 3015         drmmode_prop_info_update(drmmode, drmmode_output->props_connector,
 3016                                  DRMMODE_CONNECTOR__COUNT, props);
 3017     } else {
 3018         drmmode_output->dpms_enum_id =
 3019             koutput_get_prop_id(drmmode->fd, koutput, DRM_MODE_PROP_ENUM,
 3020                                 "DPMS");
 3021     }
 3022 
 3023     if (dynamic)
 3024         output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
 3025     return 1;
 3026 
 3027  out_free_encoders:
 3028     if (kencoders) {
 3029         for (i = 0; i < koutput->count_encoders; i++)
 3030             drmModeFreeEncoder(kencoders[i]);
 3031         free(kencoders);
 3032     }
 3033     drmModeFreeConnector(koutput);
 3034 
 3035     return 0;
 3036 }
 3037 
 3038 static uint32_t
 3039 find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
 3040 {
 3041     drmmode_output_private_ptr drmmode_output =
 3042         output->driver_private, clone_drmout;
 3043     int i;
 3044     xf86OutputPtr clone_output;
 3045     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 3046     int index_mask = 0;
 3047 
 3048     if (drmmode_output->enc_clone_mask == 0)
 3049         return index_mask;
 3050 
 3051     for (i = 0; i < xf86_config->num_output; i++) {
 3052         clone_output = xf86_config->output[i];
 3053         clone_drmout = clone_output->driver_private;
 3054         if (output == clone_output)
 3055             continue;
 3056 
 3057         if (clone_drmout->enc_mask == 0)
 3058             continue;
 3059         if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
 3060             index_mask |= (1 << i);
 3061     }
 3062     return index_mask;
 3063 }
 3064 
 3065 static void
 3066 drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res)
 3067 {
 3068     int i, j;
 3069     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 3070 
 3071     for (i = 0; i < xf86_config->num_output; i++) {
 3072         xf86OutputPtr output = xf86_config->output[i];
 3073         drmmode_output_private_ptr drmmode_output;
 3074 
 3075         drmmode_output = output->driver_private;
 3076         drmmode_output->enc_clone_mask = 0xff;
 3077         /* and all the possible encoder clones for this output together */
 3078         for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) {
 3079             int k;
 3080 
 3081             for (k = 0; k < mode_res->count_encoders; k++) {
 3082                 if (mode_res->encoders[k] ==
 3083                     drmmode_output->mode_encoders[j]->encoder_id)
 3084                     drmmode_output->enc_mask |= (1 << k);
 3085             }
 3086 
 3087             drmmode_output->enc_clone_mask &=
 3088                 drmmode_output->mode_encoders[j]->possible_clones;
 3089         }
 3090     }
 3091 
 3092     for (i = 0; i < xf86_config->num_output; i++) {
 3093         xf86OutputPtr output = xf86_config->output[i];
 3094 
 3095         output->possible_clones = find_clones(scrn, output);
 3096     }
 3097 }
 3098 
 3099 static Bool
 3100 drmmode_set_pixmap_bo(drmmode_ptr drmmode, PixmapPtr pixmap, drmmode_bo *bo)
 3101 {
 3102 #ifdef GLAMOR_HAS_GBM
 3103     ScrnInfoPtr scrn = drmmode->scrn;
 3104 
 3105     if (!drmmode->glamor)
 3106         return TRUE;
 3107 
 3108     if (!glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo->gbm,
 3109                                                        bo->used_modifiers)) {
 3110         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create pixmap\n");
 3111         return FALSE;
 3112     }
 3113 #endif
 3114 
 3115     return TRUE;
 3116 }
 3117 
 3118 Bool
 3119 drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode)
 3120 {
 3121     ScreenPtr screen = xf86ScrnToScreen(drmmode->scrn);
 3122     PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
 3123 
 3124     if (!drmmode_set_pixmap_bo(drmmode, screen_pixmap, &drmmode->front_bo))
 3125         return FALSE;
 3126 
 3127     return TRUE;
 3128 }
 3129 
 3130 static Bool
 3131 drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
 3132 {
 3133     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 3134     modesettingPtr ms = modesettingPTR(scrn);
 3135     drmmode_ptr drmmode = &ms->drmmode;
 3136     drmmode_bo old_front;
 3137     ScreenPtr screen = xf86ScrnToScreen(scrn);
 3138     uint32_t old_fb_id;
 3139     int i, pitch, old_width, old_height, old_pitch;
 3140     int cpp = (scrn->bitsPerPixel + 7) / 8;
 3141     int kcpp = (drmmode->kbpp + 7) / 8;
 3142     PixmapPtr ppix = screen->GetScreenPixmap(screen);
 3143     void *new_pixels = NULL;
 3144 
 3145     if (scrn->virtualX == width && scrn->virtualY == height)
 3146         return TRUE;
 3147 
 3148     xf86DrvMsg(scrn->scrnIndex, X_INFO,
 3149                "Allocate new frame buffer %dx%d stride\n", width, height);
 3150 
 3151     old_width = scrn->virtualX;
 3152     old_height = scrn->virtualY;
 3153     old_pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
 3154     old_front = drmmode->front_bo;
 3155     old_fb_id = drmmode->fb_id;
 3156     drmmode->fb_id = 0;
 3157 
 3158     if (!drmmode_create_bo(drmmode, &drmmode->front_bo,
 3159                            width, height, drmmode->kbpp))
 3160         goto fail;
 3161 
 3162     pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
 3163 
 3164     scrn->virtualX = width;
 3165     scrn->virtualY = height;
 3166     scrn->displayWidth = pitch / kcpp;
 3167 
 3168     if (!drmmode->gbm) {
 3169         new_pixels = drmmode_map_front_bo(drmmode);
 3170         if (!new_pixels)
 3171             goto fail;
 3172     }
 3173 
 3174     if (drmmode->shadow_enable) {
 3175         uint32_t size = scrn->displayWidth * scrn->virtualY * cpp;
 3176         new_pixels = calloc(1, size);
 3177         if (new_pixels == NULL)
 3178             goto fail;
 3179         free(drmmode->shadow_fb);
 3180         drmmode->shadow_fb = new_pixels;
 3181     }
 3182 
 3183     if (drmmode->shadow_enable2) {
 3184         uint32_t size = scrn->displayWidth * scrn->virtualY * cpp;
 3185         void *fb2 = calloc(1, size);
 3186         free(drmmode->shadow_fb2);
 3187         drmmode->shadow_fb2 = fb2;
 3188     }
 3189 
 3190     screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
 3191                                scrn->displayWidth * cpp, new_pixels);
 3192 
 3193     if (!drmmode_glamor_handle_new_screen_pixmap(drmmode))
 3194         goto fail;
 3195 
 3196     drmmode_clear_pixmap(ppix);
 3197 
 3198     for (i = 0; i < xf86_config->num_crtc; i++) {
 3199         xf86CrtcPtr crtc = xf86_config->crtc[i];
 3200 
 3201         if (!crtc->enabled)
 3202             continue;
 3203 
 3204         drmmode_set_mode_major(crtc, &crtc->mode,
 3205                                crtc->rotation, crtc->x, crtc->y);
 3206     }
 3207 
 3208     if (old_fb_id) {
 3209         drmModeRmFB(drmmode->fd, old_fb_id);
 3210         drmmode_bo_destroy(drmmode, &old_front);
 3211     }
 3212 
 3213     return TRUE;
 3214 
 3215  fail:
 3216     drmmode_bo_destroy(drmmode, &drmmode->front_bo);
 3217     drmmode->front_bo = old_front;
 3218     scrn->virtualX = old_width;
 3219     scrn->virtualY = old_height;
 3220     scrn->displayWidth = old_pitch / kcpp;
 3221     drmmode->fb_id = old_fb_id;
 3222 
 3223     return FALSE;
 3224 }
 3225 
 3226 static void
 3227 drmmode_validate_leases(ScrnInfoPtr scrn)
 3228 {
 3229     ScreenPtr screen = scrn->pScreen;
 3230     rrScrPrivPtr scr_priv;
 3231     modesettingPtr ms = modesettingPTR(scrn);
 3232     drmmode_ptr drmmode = &ms->drmmode;
 3233     drmModeLesseeListPtr lessees;
 3234     RRLeasePtr lease, next;
 3235     int l;
 3236 
 3237     /* Bail out if RandR wasn't initialized. */
 3238     if (!dixPrivateKeyRegistered(rrPrivKey))
 3239         return;
 3240 
 3241     scr_priv = rrGetScrPriv(screen);
 3242 
 3243     /* We can't talk to the kernel about leases when VT switched */
 3244     if (!scrn->vtSema)
 3245         return;
 3246 
 3247     lessees = drmModeListLessees(drmmode->fd);
 3248     if (!lessees)
 3249         return;
 3250 
 3251     xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) {
 3252         drmmode_lease_private_ptr lease_private = lease->devPrivate;
 3253 
 3254         for (l = 0; l < lessees->count; l++) {
 3255             if (lessees->lessees[l] == lease_private->lessee_id)
 3256                 break;
 3257         }
 3258 
 3259         /* check to see if the lease has gone away */
 3260         if (l == lessees->count) {
 3261             free(lease_private);
 3262             lease->devPrivate = NULL;
 3263             xf86CrtcLeaseTerminated(lease);
 3264         }
 3265     }
 3266 
 3267     free(lessees);
 3268 }
 3269 
 3270 static int
 3271 drmmode_create_lease(RRLeasePtr lease, int *fd)
 3272 {
 3273     ScreenPtr screen = lease->screen;
 3274     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
 3275     modesettingPtr ms = modesettingPTR(scrn);
 3276     drmmode_ptr drmmode = &ms->drmmode;
 3277     int ncrtc = lease->numCrtcs;
 3278     int noutput = lease->numOutputs;
 3279     int nobjects;
 3280     int c, o;
 3281     int i;
 3282     int lease_fd;
 3283     uint32_t *objects;
 3284     drmmode_lease_private_ptr   lease_private;
 3285 
 3286     nobjects = ncrtc + noutput;
 3287 
 3288     if (ms->atomic_modeset)
 3289         nobjects += ncrtc; /* account for planes as well */
 3290 
 3291     if (nobjects == 0)
 3292         return BadValue;
 3293 
 3294     lease_private = calloc(1, sizeof (drmmode_lease_private_rec));
 3295     if (!lease_private)
 3296         return BadAlloc;
 3297 
 3298     objects = xallocarray(nobjects, sizeof (uint32_t));
 3299 
 3300     if (!objects) {
 3301         free(lease_private);
 3302         return BadAlloc;
 3303     }
 3304 
 3305     i = 0;
 3306 
 3307     /* Add CRTC and plane ids */
 3308     for (c = 0; c < ncrtc; c++) {
 3309         xf86CrtcPtr crtc = lease->crtcs[c]->devPrivate;
 3310         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 3311 
 3312         objects[i++] = drmmode_crtc->mode_crtc->crtc_id;
 3313         if (ms->atomic_modeset)
 3314             objects[i++] = drmmode_crtc->plane_id;
 3315     }
 3316 
 3317     /* Add connector ids */
 3318 
 3319     for (o = 0; o < noutput; o++) {
 3320         xf86OutputPtr   output = lease->outputs[o]->devPrivate;
 3321         drmmode_output_private_ptr drmmode_output = output->driver_private;
 3322 
 3323         objects[i++] = drmmode_output->mode_output->connector_id;
 3324     }
 3325 
 3326     /* call kernel to create lease */
 3327     assert (i == nobjects);
 3328 
 3329     lease_fd = drmModeCreateLease(drmmode->fd, objects, nobjects, 0, &lease_private->lessee_id);
 3330 
 3331     free(objects);
 3332 
 3333     if (lease_fd < 0) {
 3334         free(lease_private);
 3335         return BadMatch;
 3336     }
 3337 
 3338     lease->devPrivate = lease_private;
 3339 
 3340     xf86CrtcLeaseStarted(lease);
 3341 
 3342     *fd = lease_fd;
 3343     return Success;
 3344 }
 3345 
 3346 static void
 3347 drmmode_terminate_lease(RRLeasePtr lease)
 3348 {
 3349     ScreenPtr screen = lease->screen;
 3350     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
 3351     modesettingPtr ms = modesettingPTR(scrn);
 3352     drmmode_ptr drmmode = &ms->drmmode;
 3353     drmmode_lease_private_ptr lease_private = lease->devPrivate;
 3354 
 3355     if (drmModeRevokeLease(drmmode->fd, lease_private->lessee_id) == 0) {
 3356         free(lease_private);
 3357         lease->devPrivate = NULL;
 3358         xf86CrtcLeaseTerminated(lease);
 3359     }
 3360 }
 3361 
 3362 static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 3363     .resize = drmmode_xf86crtc_resize,
 3364     .create_lease = drmmode_create_lease,
 3365     .terminate_lease = drmmode_terminate_lease
 3366 };
 3367 
 3368 Bool
 3369 drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 3370 {
 3371     modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
 3372     int i;
 3373     int ret;
 3374     uint64_t value = 0;
 3375     unsigned int crtcs_needed = 0;
 3376     drmModeResPtr mode_res;
 3377     int crtcshift;
 3378 
 3379     /* check for dumb capability */
 3380     ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value);
 3381     if (ret > 0 || value != 1) {
 3382         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 3383                    "KMS doesn't support dumb interface\n");
 3384         return FALSE;
 3385     }
 3386 
 3387     xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
 3388 
 3389     drmmode->scrn = pScrn;
 3390     drmmode->cpp = cpp;
 3391     mode_res = drmModeGetResources(drmmode->fd);
 3392     if (!mode_res)
 3393         return FALSE;
 3394 
 3395     crtcshift = ffs(ms_ent->assigned_crtcs ^ 0xffffffff) - 1;
 3396     for (i = 0; i < mode_res->count_connectors; i++)
 3397         crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE,
 3398                                             crtcshift);
 3399 
 3400     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
 3401                    "Up to %d crtcs needed for screen.\n", crtcs_needed);
 3402 
 3403     xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width,
 3404                          mode_res->max_height);
 3405     for (i = 0; i < mode_res->count_crtcs; i++)
 3406         if (!xf86IsEntityShared(pScrn->entityList[0]) ||
 3407             (crtcs_needed && !(ms_ent->assigned_crtcs & (1 << i))))
 3408             crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
 3409 
 3410     /* All ZaphodHeads outputs provided with matching crtcs? */
 3411     if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
 3412         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 3413                    "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n",
 3414                    crtcs_needed);
 3415 
 3416     /* workout clones */
 3417     drmmode_clones_init(pScrn, drmmode, mode_res);
 3418 
 3419     drmModeFreeResources(mode_res);
 3420     xf86ProviderSetup(pScrn, NULL, "modesetting");
 3421 
 3422     xf86InitialConfiguration(pScrn, TRUE);
 3423 
 3424     return TRUE;
 3425 }
 3426 
 3427 Bool
 3428 drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 3429 {
 3430 #ifdef GLAMOR_HAS_GBM
 3431     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
 3432 
 3433     if (drmmode->glamor) {
 3434         if (!glamor_init(pScreen, GLAMOR_USE_EGL_SCREEN)) {
 3435             return FALSE;
 3436         }
 3437 #ifdef GBM_BO_WITH_MODIFIERS
 3438         glamor_set_drawable_modifiers_func(pScreen, get_drawable_modifiers);
 3439 #endif
 3440     }
 3441 #endif
 3442 
 3443     return TRUE;
 3444 }
 3445 
 3446 void
 3447 drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
 3448 {
 3449     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
 3450     xf86OutputPtr output = config->output[config->compat_output];
 3451     xf86CrtcPtr crtc = output->crtc;
 3452 
 3453     if (crtc && crtc->enabled) {
 3454         drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, x, y);
 3455     }
 3456 }
 3457 
 3458 Bool
 3459 drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw)
 3460 {
 3461     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
 3462     int c;
 3463 
 3464     for (c = 0; c < config->num_crtc; c++) {
 3465         xf86CrtcPtr crtc = config->crtc[c];
 3466         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 3467         xf86OutputPtr output = NULL;
 3468         int o;
 3469 
 3470         /* Skip disabled CRTCs */
 3471         if (!crtc->enabled) {
 3472             if (set_hw) {
 3473                 drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 3474                                0, 0, 0, NULL, 0, NULL);
 3475             }
 3476             continue;
 3477         }
 3478 
 3479         if (config->output[config->compat_output]->crtc == crtc)
 3480             output = config->output[config->compat_output];
 3481         else {
 3482             for (o = 0; o < config->num_output; o++)
 3483                 if (config->output[o]->crtc == crtc) {
 3484                     output = config->output[o];
 3485                     break;
 3486                 }
 3487         }
 3488         /* paranoia */
 3489         if (!output)
 3490             continue;
 3491 
 3492         /* Mark that we'll need to re-set the mode for sure */
 3493         memset(&crtc->mode, 0, sizeof(crtc->mode));
 3494         if (!crtc->desiredMode.CrtcHDisplay) {
 3495             DisplayModePtr mode =
 3496                 xf86OutputFindClosestMode(output, pScrn->currentMode);
 3497 
 3498             if (!mode)
 3499                 return FALSE;
 3500             crtc->desiredMode = *mode;
 3501             crtc->desiredRotation = RR_Rotate_0;
 3502             crtc->desiredX = 0;
 3503             crtc->desiredY = 0;
 3504         }
 3505 
 3506         if (set_hw) {
 3507             if (!crtc->funcs->
 3508                 set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
 3509                                crtc->desiredX, crtc->desiredY))
 3510                 return FALSE;
 3511         } else {
 3512             crtc->mode = crtc->desiredMode;
 3513             crtc->rotation = crtc->desiredRotation;
 3514             crtc->x = crtc->desiredX;
 3515             crtc->y = crtc->desiredY;
 3516             if (!xf86CrtcRotate(crtc))
 3517                 return FALSE;
 3518         }
 3519     }
 3520 
 3521     /* Validate leases on VT re-entry */
 3522     drmmode_validate_leases(pScrn);
 3523 
 3524     return TRUE;
 3525 }
 3526 
 3527 static void
 3528 drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
 3529                      int *indices, LOCO * colors, VisualPtr pVisual)
 3530 {
 3531     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 3532     uint16_t lut_r[256], lut_g[256], lut_b[256];
 3533     int index, j, i;
 3534     int c;
 3535 
 3536     for (c = 0; c < xf86_config->num_crtc; c++) {
 3537         xf86CrtcPtr crtc = xf86_config->crtc[c];
 3538         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 3539 
 3540         for (i = 0; i < 256; i++) {
 3541             lut_r[i] = drmmode_crtc->lut_r[i] << 6;
 3542             lut_g[i] = drmmode_crtc->lut_g[i] << 6;
 3543             lut_b[i] = drmmode_crtc->lut_b[i] << 6;
 3544         }
 3545 
 3546         switch (pScrn->depth) {
 3547         case 15:
 3548             for (i = 0; i < numColors; i++) {
 3549                 index = indices[i];
 3550                 for (j = 0; j < 8; j++) {
 3551                     lut_r[index * 8 + j] = colors[index].red << 6;
 3552                     lut_g[index * 8 + j] = colors[index].green << 6;
 3553                     lut_b[index * 8 + j] = colors[index].blue << 6;
 3554                 }
 3555             }
 3556             break;
 3557         case 16:
 3558             for (i = 0; i < numColors; i++) {
 3559                 index = indices[i];
 3560 
 3561                 if (i <= 31) {
 3562                     for (j = 0; j < 8; j++) {
 3563                         lut_r[index * 8 + j] = colors[index].red << 6;
 3564                         lut_b[index * 8 + j] = colors[index].blue << 6;
 3565                     }
 3566                 }
 3567 
 3568                 for (j = 0; j < 4; j++) {
 3569                     lut_g[index * 4 + j] = colors[index].green << 6;
 3570                 }
 3571             }
 3572             break;
 3573         default:
 3574             for (i = 0; i < numColors; i++) {
 3575                 index = indices[i];
 3576                 lut_r[index] = colors[index].red << 6;
 3577                 lut_g[index] = colors[index].green << 6;
 3578                 lut_b[index] = colors[index].blue << 6;
 3579             }
 3580             break;
 3581         }
 3582 
 3583         /* Make the change through RandR */
 3584         if (crtc->randr_crtc)
 3585             RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
 3586         else
 3587             crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
 3588     }
 3589 }
 3590 
 3591 Bool
 3592 drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
 3593 {
 3594     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
 3595                    "Initializing kms color map for depth %d, %d bpc.\n",
 3596                    pScrn->depth, pScrn->rgbBits);
 3597     if (!miCreateDefColormap(pScreen))
 3598         return FALSE;
 3599 
 3600     /* Adapt color map size and depth to color depth of screen. */
 3601     if (!xf86HandleColormaps(pScreen, 1 << pScrn->rgbBits, 10,
 3602                              drmmode_load_palette, NULL,
 3603                              CMAP_PALETTED_TRUECOLOR |
 3604                              CMAP_RELOAD_ON_MODE_SWITCH))
 3605         return FALSE;
 3606     return TRUE;
 3607 }
 3608 
 3609 #ifdef CONFIG_UDEV_KMS
 3610 
 3611 #define DRM_MODE_LINK_STATUS_GOOD       0
 3612 #define DRM_MODE_LINK_STATUS_BAD        1
 3613 
 3614 static void
 3615 drmmode_handle_uevents(int fd, void *closure)
 3616 {
 3617     drmmode_ptr drmmode = closure;
 3618     ScrnInfoPtr scrn = drmmode->scrn;
 3619     struct udev_device *dev;
 3620     drmModeResPtr mode_res;
 3621     xf86CrtcConfigPtr  config = XF86_CRTC_CONFIG_PTR(scrn);
 3622     int i, j;
 3623     Bool found = FALSE;
 3624     Bool changed = FALSE;
 3625 
 3626     while ((dev = udev_monitor_receive_device(drmmode->uevent_monitor))) {
 3627         udev_device_unref(dev);
 3628         found = TRUE;
 3629     }
 3630     if (!found)
 3631         return;
 3632 
 3633     /* Try to re-set the mode on all the connectors with a BAD link-state:
 3634      * This may happen if a link degrades and a new modeset is necessary, using
 3635      * different link-training parameters. If the kernel found that the current
 3636      * mode is not achievable anymore, it should have pruned the mode before
 3637      * sending the hotplug event. Try to re-set the currently-set mode to keep
 3638      * the display alive, this will fail if the mode has been pruned.
 3639      * In any case, we will send randr events for the Desktop Environment to
 3640      * deal with it, if it wants to.
 3641      */
 3642     for (i = 0; i < config->num_output; i++) {
 3643         xf86OutputPtr output = config->output[i];
 3644         drmmode_output_private_ptr drmmode_output = output->driver_private;
 3645 
 3646         drmmode_output_detect(output);
 3647 
 3648         /* Get an updated view of the properties for the current connector and
 3649          * look for the link-status property
 3650          */
 3651         for (j = 0; j < drmmode_output->num_props; j++) {
 3652             drmmode_prop_ptr p = &drmmode_output->props[j];
 3653 
 3654             if (!strcmp(p->mode_prop->name, "link-status")) {
 3655                 if (p->value == DRM_MODE_LINK_STATUS_BAD) {
 3656                     xf86CrtcPtr crtc = output->crtc;
 3657                     if (!crtc)
 3658                         continue;
 3659 
 3660                     /* the connector got a link failure, re-set the current mode */
 3661                     drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
 3662                                            crtc->x, crtc->y);
 3663 
 3664                     xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 3665                                "hotplug event: connector %u's link-state is BAD, "
 3666                                "tried resetting the current mode. You may be left"
 3667                                "with a black screen if this fails...\n",
 3668                                drmmode_output->mode_output->connector_id);
 3669                 }
 3670                 break;
 3671             }
 3672         }
 3673     }
 3674 
 3675     mode_res = drmModeGetResources(drmmode->fd);
 3676     if (!mode_res)
 3677         goto out;
 3678 
 3679     if (mode_res->count_crtcs != config->num_crtc) {
 3680         /* this triggers with Zaphod mode where we don't currently support connector hotplug or MST. */
 3681         goto out_free_res;
 3682     }
 3683 
 3684     /* figure out if we have gotten rid of any connectors
 3685        traverse old output list looking for outputs */
 3686     for (i = 0; i < config->num_output; i++) {
 3687         xf86OutputPtr output = config->output[i];
 3688         drmmode_output_private_ptr drmmode_output;
 3689 
 3690         drmmode_output = output->driver_private;
 3691         found = FALSE;
 3692         for (j = 0; j < mode_res->count_connectors; j++) {
 3693             if (mode_res->connectors[j] == drmmode_output->output_id) {
 3694                 found = TRUE;
 3695                 break;
 3696             }
 3697         }
 3698         if (found)
 3699             continue;
 3700 
 3701         drmModeFreeConnector(drmmode_output->mode_output);
 3702         drmmode_output->mode_output = NULL;
 3703         drmmode_output->output_id = -1;
 3704 
 3705         changed = TRUE;
 3706     }
 3707 
 3708     /* find new output ids we don't have outputs for */
 3709     for (i = 0; i < mode_res->count_connectors; i++) {
 3710         found = FALSE;
 3711 
 3712         for (j = 0; j < config->num_output; j++) {
 3713             xf86OutputPtr output = config->output[j];
 3714             drmmode_output_private_ptr drmmode_output;
 3715 
 3716             drmmode_output = output->driver_private;
 3717             if (mode_res->connectors[i] == drmmode_output->output_id) {
 3718                 found = TRUE;
 3719                 break;
 3720             }
 3721         }
 3722         if (found)
 3723             continue;
 3724 
 3725         changed = TRUE;
 3726         drmmode_output_init(scrn, drmmode, mode_res, i, TRUE, 0);
 3727     }
 3728 
 3729     if (changed) {
 3730         RRSetChanged(xf86ScrnToScreen(scrn));
 3731         RRTellChanged(xf86ScrnToScreen(scrn));
 3732     }
 3733 
 3734 out_free_res:
 3735 
 3736     /* Check to see if a lessee has disappeared */
 3737     drmmode_validate_leases(scrn);
 3738 
 3739     drmModeFreeResources(mode_res);
 3740 out:
 3741     RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
 3742 }
 3743 
 3744 #undef DRM_MODE_LINK_STATUS_BAD
 3745 #undef DRM_MODE_LINK_STATUS_GOOD
 3746 
 3747 #endif
 3748 
 3749 void
 3750 drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
 3751 {
 3752 #ifdef CONFIG_UDEV_KMS
 3753     struct udev *u;
 3754     struct udev_monitor *mon;
 3755 
 3756     u = udev_new();
 3757     if (!u)
 3758         return;
 3759     mon = udev_monitor_new_from_netlink(u, "udev");
 3760     if (!mon) {
 3761         udev_unref(u);
 3762         return;
 3763     }
 3764 
 3765     if (udev_monitor_filter_add_match_subsystem_devtype(mon,
 3766                                                         "drm",
 3767                                                         "drm_minor") < 0 ||
 3768         udev_monitor_enable_receiving(mon) < 0) {
 3769         udev_monitor_unref(mon);
 3770         udev_unref(u);
 3771         return;
 3772     }
 3773 
 3774     drmmode->uevent_handler =
 3775         xf86AddGeneralHandler(udev_monitor_get_fd(mon),
 3776                               drmmode_handle_uevents, drmmode);
 3777 
 3778     drmmode->uevent_monitor = mon;
 3779 #endif
 3780 }
 3781 
 3782 void
 3783 drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
 3784 {
 3785 #ifdef CONFIG_UDEV_KMS
 3786     if (drmmode->uevent_handler) {
 3787         struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
 3788 
 3789         xf86RemoveGeneralHandler(drmmode->uevent_handler);
 3790 
 3791         udev_monitor_unref(drmmode->uevent_monitor);
 3792         udev_unref(u);
 3793     }
 3794 #endif
 3795 }
 3796 
 3797 /* create front and cursor BOs */
 3798 Bool
 3799 drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 3800 {
 3801     modesettingPtr ms = modesettingPTR(pScrn);
 3802     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 3803     int width;
 3804     int height;
 3805     int bpp = ms->drmmode.kbpp;
 3806     int i;
 3807     int cpp = (bpp + 7) / 8;
 3808 
 3809     width = pScrn->virtualX;
 3810     height = pScrn->virtualY;
 3811 
 3812     if (!drmmode_create_bo(drmmode, &drmmode->front_bo, width, height, bpp))
 3813         return FALSE;
 3814     pScrn->displayWidth = drmmode_bo_get_pitch(&drmmode->front_bo) / cpp;
 3815 
 3816     width = ms->cursor_width;
 3817     height = ms->cursor_height;
 3818     bpp = 32;
 3819     for (i = 0; i < xf86_config->num_crtc; i++) {
 3820         xf86CrtcPtr crtc = xf86_config->crtc[i];
 3821         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 3822 
 3823         drmmode_crtc->cursor_bo =
 3824             dumb_bo_create(drmmode->fd, width, height, bpp);
 3825     }
 3826     return TRUE;
 3827 }
 3828 
 3829 void *
 3830 drmmode_map_front_bo(drmmode_ptr drmmode)
 3831 {
 3832     return drmmode_bo_map(drmmode, &drmmode->front_bo);
 3833 }
 3834 
 3835 void *
 3836 drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv)
 3837 {
 3838     int ret;
 3839 
 3840     if (ppriv->backing_bo->ptr)
 3841         return ppriv->backing_bo->ptr;
 3842 
 3843     ret = dumb_bo_map(drmmode->fd, ppriv->backing_bo);
 3844     if (ret)
 3845         return NULL;
 3846 
 3847     return ppriv->backing_bo->ptr;
 3848 }
 3849 
 3850 Bool
 3851 drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 3852 {
 3853     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 3854     int i, ret;
 3855 
 3856     for (i = 0; i < xf86_config->num_crtc; i++) {
 3857         xf86CrtcPtr crtc = xf86_config->crtc[i];
 3858         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 3859 
 3860         ret = dumb_bo_map(drmmode->fd, drmmode_crtc->cursor_bo);
 3861         if (ret)
 3862             return FALSE;
 3863     }
 3864     return TRUE;
 3865 }
 3866 
 3867 void
 3868 drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 3869 {
 3870     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 3871     int i;
 3872 
 3873     if (drmmode->fb_id) {
 3874         drmModeRmFB(drmmode->fd, drmmode->fb_id);
 3875         drmmode->fb_id = 0;
 3876     }
 3877 
 3878     drmmode_bo_destroy(drmmode, &drmmode->front_bo);
 3879 
 3880     for (i = 0; i < xf86_config->num_crtc; i++) {
 3881         xf86CrtcPtr crtc = xf86_config->crtc[i];
 3882         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 3883 
 3884         dumb_bo_destroy(drmmode->fd, drmmode_crtc->cursor_bo);
 3885     }
 3886 }
 3887 
 3888 /* ugly workaround to see if we can create 32bpp */
 3889 void
 3890 drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int *depth,
 3891                         int *bpp)
 3892 {
 3893     drmModeResPtr mode_res;
 3894     uint64_t value;
 3895     struct dumb_bo *bo;
 3896     uint32_t fb_id;
 3897     int ret;
 3898 
 3899     /* 16 is fine */
 3900     ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_PREFERRED_DEPTH, &value);
 3901     if (!ret && (value == 16 || value == 8)) {
 3902         *depth = value;
 3903         *bpp = value;
 3904         return;
 3905     }
 3906 
 3907     *depth = 24;
 3908     mode_res = drmModeGetResources(drmmode->fd);
 3909     if (!mode_res)
 3910         return;
 3911 
 3912     if (mode_res->min_width == 0)
 3913         mode_res->min_width = 1;
 3914     if (mode_res->min_height == 0)
 3915         mode_res->min_height = 1;
 3916     /*create a bo */
 3917     bo = dumb_bo_create(drmmode->fd, mode_res->min_width, mode_res->min_height,
 3918                         32);
 3919     if (!bo) {
 3920         *bpp = 24;
 3921         goto out;
 3922     }
 3923 
 3924     ret = drmModeAddFB(drmmode->fd, mode_res->min_width, mode_res->min_height,
 3925                        24, 32, bo->pitch, bo->handle, &fb_id);
 3926 
 3927     if (ret) {
 3928         *bpp = 24;
 3929         dumb_bo_destroy(drmmode->fd, bo);
 3930         goto out;
 3931     }
 3932 
 3933     drmModeRmFB(drmmode->fd, fb_id);
 3934     *bpp = 32;
 3935 
 3936     dumb_bo_destroy(drmmode->fd, bo);
 3937  out:
 3938     drmModeFreeResources(mode_res);
 3939     return;
 3940 }