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