xserver

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

dri3_screen.c (9889B)


      1 /*
      2  * Copyright © 2013 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 #include "dri3_priv.h"
     24 #include <syncsdk.h>
     25 #include <misync.h>
     26 #include <misyncshm.h>
     27 #include <randrstr.h>
     28 #include <drm_fourcc.h>
     29 #include <unistd.h>
     30 
     31 int
     32 dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
     33 {
     34     dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
     35     const dri3_screen_info_rec *info = ds->info;
     36 
     37     if (info == NULL)
     38         return BadMatch;
     39 
     40     if (info->version >= 1 && info->open_client != NULL)
     41         return (*info->open_client) (client, screen, provider, fd);
     42     if (info->open != NULL)
     43         return (*info->open) (screen, provider, fd);
     44 
     45     return BadMatch;
     46 }
     47 
     48 int
     49 dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen,
     50                      CARD8 num_fds, const int *fds,
     51                      CARD16 width, CARD16 height,
     52                      const CARD32 *strides, const CARD32 *offsets,
     53                      CARD8 depth, CARD8 bpp, CARD64 modifier)
     54 {
     55     dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
     56     const dri3_screen_info_rec *info = ds->info;
     57     PixmapPtr                   pixmap;
     58 
     59     if (!info)
     60         return BadImplementation;
     61 
     62     if (info->version >= 2 && info->pixmap_from_fds != NULL) {
     63         pixmap = (*info->pixmap_from_fds) (screen, num_fds, fds, width, height,
     64                                            strides, offsets, depth, bpp, modifier);
     65     } else if (info->pixmap_from_fd != NULL && num_fds == 1) {
     66         pixmap = (*info->pixmap_from_fd) (screen, fds[0], width, height,
     67                                           strides[0], depth, bpp);
     68     } else {
     69         return BadImplementation;
     70     }
     71 
     72     if (!pixmap)
     73         return BadAlloc;
     74 
     75     *ppixmap = pixmap;
     76     return Success;
     77 }
     78 
     79 int
     80 dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
     81                      uint32_t *strides, uint32_t *offsets,
     82                      uint64_t *modifier)
     83 {
     84     ScreenPtr                   screen = pixmap->drawable.pScreen;
     85     dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
     86     const dri3_screen_info_rec *info = ds->info;
     87 
     88     if (!info)
     89         return 0;
     90 
     91     if (info->version >= 2 && info->fds_from_pixmap != NULL) {
     92         return (*info->fds_from_pixmap)(screen, pixmap, fds, strides, offsets,
     93                                         modifier);
     94     } else if (info->fd_from_pixmap != NULL) {
     95         CARD16 stride;
     96         CARD32 size;
     97 
     98         fds[0] = (*info->fd_from_pixmap)(screen, pixmap, &stride, &size);
     99         if (fds[0] < 0)
    100             return 0;
    101 
    102         strides[0] = stride;
    103         offsets[0] = 0;
    104         *modifier = DRM_FORMAT_MOD_INVALID;
    105         return 1;
    106     } else {
    107         return 0;
    108     }
    109 }
    110 
    111 int
    112 dri3_fd_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
    113 {
    114     ScreenPtr                   screen = pixmap->drawable.pScreen;
    115     dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
    116     const dri3_screen_info_rec  *info = ds->info;
    117     uint32_t                    strides[4];
    118     uint32_t                    offsets[4];
    119     uint64_t                    modifier;
    120     int                         fds[4];
    121     int                         num_fds;
    122 
    123     if (!info)
    124         return -1;
    125 
    126     /* Preferentially use the old interface, allowing the implementation to
    127      * ensure the buffer is in a single-plane format which doesn't need
    128      * modifiers. */
    129     if (info->fd_from_pixmap != NULL)
    130         return (*info->fd_from_pixmap)(screen, pixmap, stride, size);
    131 
    132     if (info->version < 2 || info->fds_from_pixmap == NULL)
    133         return -1;
    134 
    135     /* If using the new interface, make sure that it's a single plane starting
    136      * at 0 within the BO. We don't check the modifier, as the client may
    137      * have an auxiliary mechanism for determining the modifier itself. */
    138     num_fds = info->fds_from_pixmap(screen, pixmap, fds, strides, offsets,
    139                                     &modifier);
    140     if (num_fds != 1 || offsets[0] != 0) {
    141         int i;
    142         for (i = 0; i < num_fds; i++)
    143             close(fds[i]);
    144         return -1;
    145     }
    146 
    147     *stride = strides[0];
    148     *size = size[0];
    149     return fds[0];
    150 }
    151 
    152 static int
    153 cache_formats_and_modifiers(ScreenPtr screen)
    154 {
    155     dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
    156     const dri3_screen_info_rec *info = ds->info;
    157     CARD32                      num_formats;
    158     CARD32                     *formats;
    159     uint32_t                    num_modifiers;
    160     uint64_t                   *modifiers;
    161     int                         i;
    162 
    163     if (ds->formats_cached)
    164         return Success;
    165 
    166     if (!info)
    167         return BadImplementation;
    168 
    169     if (info->version < 2 || !info->get_formats || !info->get_modifiers) {
    170         ds->formats = NULL;
    171         ds->num_formats = 0;
    172         ds->formats_cached = TRUE;
    173         return Success;
    174     }
    175 
    176     if (!info->get_formats(screen, &num_formats, &formats))
    177         return BadAlloc;
    178 
    179     if (!num_formats) {
    180         ds->num_formats = 0;
    181         ds->formats_cached = TRUE;
    182         return Success;
    183     }
    184 
    185     ds->formats = calloc(num_formats, sizeof(dri3_dmabuf_format_rec));
    186     if (!ds->formats)
    187         return BadAlloc;
    188 
    189     for (i = 0; i < num_formats; i++) {
    190         dri3_dmabuf_format_ptr iter = &ds->formats[i];
    191 
    192         if (!info->get_modifiers(screen, formats[i],
    193                                  &num_modifiers,
    194                                  &modifiers))
    195             continue;
    196 
    197         if (!num_modifiers)
    198             continue;
    199 
    200         iter->format = formats[i];
    201         iter->num_modifiers = num_modifiers;
    202         iter->modifiers = modifiers;
    203     }
    204 
    205     ds->num_formats = i;
    206     ds->formats_cached = TRUE;
    207 
    208     return Success;
    209 }
    210 
    211 int
    212 dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
    213                              CARD8 depth, CARD8 bpp,
    214                              CARD32 *num_intersect_modifiers,
    215                              CARD64 **intersect_modifiers,
    216                              CARD32 *num_screen_modifiers,
    217                              CARD64 **screen_modifiers)
    218 {
    219     dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
    220     const dri3_screen_info_rec *info = ds->info;
    221     int                         i, j;
    222     int                         ret;
    223     uint32_t                    num_drawable_mods;
    224     uint64_t                   *drawable_mods;
    225     CARD64                     *intersect_mods = NULL;
    226     CARD64                     *screen_mods = NULL;
    227     CARD32                      format;
    228     dri3_dmabuf_format_ptr      screen_format = NULL;
    229 
    230     ret = cache_formats_and_modifiers(screen);
    231     if (ret != Success)
    232         return ret;
    233 
    234     format = drm_format_for_depth(depth, bpp);
    235     if (format == 0)
    236         return BadValue;
    237 
    238     /* Find screen-global modifiers from cache
    239      */
    240     for (i = 0; i < ds->num_formats; i++) {
    241         if (ds->formats[i].format == format) {
    242             screen_format = &ds->formats[i];
    243             break;
    244         }
    245     }
    246     if (screen_format == NULL)
    247         return BadMatch;
    248 
    249     if (screen_format->num_modifiers == 0) {
    250         *num_screen_modifiers = 0;
    251         *num_intersect_modifiers = 0;
    252         return Success;
    253     }
    254 
    255     if (!info->get_drawable_modifiers ||
    256         !info->get_drawable_modifiers(drawable, format,
    257                                       &num_drawable_mods,
    258                                       &drawable_mods)) {
    259         num_drawable_mods = 0;
    260         drawable_mods = NULL;
    261     }
    262 
    263     /* We're allocating slightly more memory than necessary but it reduces
    264      * the complexity of finding the intersection set.
    265      */
    266     screen_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
    267     if (!screen_mods)
    268         return BadAlloc;
    269     if (num_drawable_mods > 0) {
    270         intersect_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
    271         if (!intersect_mods) {
    272             free(screen_mods);
    273             return BadAlloc;
    274         }
    275     }
    276 
    277     *num_screen_modifiers = 0;
    278     *num_intersect_modifiers = 0;
    279     for (i = 0; i < screen_format->num_modifiers; i++) {
    280         CARD64 modifier = screen_format->modifiers[i];
    281         Bool intersect = FALSE;
    282 
    283         for (j = 0; j < num_drawable_mods; j++) {
    284             if (drawable_mods[j] == modifier) {
    285                 intersect = TRUE;
    286                 break;
    287             }
    288         }
    289 
    290         if (intersect) {
    291             intersect_mods[*num_intersect_modifiers] = modifier;
    292             *num_intersect_modifiers += 1;
    293         } else {
    294             screen_mods[*num_screen_modifiers] = modifier;
    295             *num_screen_modifiers += 1;
    296         }
    297     }
    298 
    299     assert(*num_intersect_modifiers + *num_screen_modifiers == screen_format->num_modifiers);
    300 
    301     *intersect_modifiers = intersect_mods;
    302     *screen_modifiers = screen_mods;
    303     free(drawable_mods);
    304 
    305     return Success;
    306 }