xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/drivers/modesetting/dri3.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *  Copyright (c) 2020, Fuzhou Rockchip Electronics Co., Ltd
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  */
14 
15 #ifdef HAVE_DIX_CONFIG_H
16 #include "dix-config.h"
17 #endif
18 
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <drm_fourcc.h>
22 
23 #include "xf86.h"
24 
25 #include "dri3.h"
26 #include "driver.h"
27 
28 /* Based on glamor/glamor_egl.c#glamor_dri3_open_client */
29 static int
ms_exa_dri3_open_client(ClientPtr client,ScreenPtr screen,RRProviderPtr provider,int * fdp)30 ms_exa_dri3_open_client(ClientPtr client,
31                         ScreenPtr screen,
32                         RRProviderPtr provider,
33                         int *fdp)
34 {
35     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
36     modesettingPtr ms = modesettingPTR(scrn);
37     int fd;
38     drm_magic_t magic;
39 
40     fd = open(ms->drmmode.dri3_device_name, O_RDWR|O_CLOEXEC);
41     if (fd < 0)
42         return BadAlloc;
43 
44     /* Before FD passing in the X protocol with DRI3 (and increased
45      * security of rendering with per-process address spaces on the
46      * GPU), the kernel had to come up with a way to have the server
47      * decide which clients got to access the GPU, which was done by
48      * each client getting a unique (magic) number from the kernel,
49      * passing it to the server, and the server then telling the
50      * kernel which clients were authenticated for using the device.
51      *
52      * Now that we have FD passing, the server can just set up the
53      * authentication on its own and hand the prepared FD off to the
54      * client.
55      */
56     if (drmGetMagic(fd, &magic) < 0) {
57         if (errno == EACCES) {
58             /* Assume that we're on a render node, and the fd is
59              * already as authenticated as it should be.
60              */
61             *fdp = fd;
62             return Success;
63         } else {
64             close(fd);
65             return BadMatch;
66         }
67     }
68 
69     if (drmAuthMagic(ms->drmmode.fd, magic) < 0) {
70         close(fd);
71         return BadMatch;
72     }
73 
74     *fdp = fd;
75     return Success;
76 }
77 
78 static PixmapPtr
ms_exa_pixmap_from_fds(ScreenPtr screen,CARD8 num_fds,const int * fds,CARD16 width,CARD16 height,const CARD32 * strides,const CARD32 * offsets,CARD8 depth,CARD8 bpp,uint64_t modifier)79 ms_exa_pixmap_from_fds(ScreenPtr screen,
80                        CARD8 num_fds, const int *fds,
81                        CARD16 width, CARD16 height,
82                        const CARD32 *strides, const CARD32 *offsets,
83                        CARD8 depth, CARD8 bpp,
84                        uint64_t modifier)
85 {
86     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
87     modesettingPtr ms = modesettingPTR(scrn);
88 	PixmapPtr pixmap;
89 	struct dumb_bo *bo;
90 
91     if (num_fds != 1 || offsets[0] || modifier != DRM_FORMAT_MOD_INVALID)
92         return NULL;
93 
94     pixmap = drmmode_create_pixmap_header(screen, width, height,
95                                           depth, bpp, strides[0], NULL);
96     if (!pixmap)
97         return NULL;
98 
99     bo = dumb_get_bo_from_fd(ms->drmmode.fd, fds[0],
100                              strides[0], strides[0] * height);
101     if (!bo)
102         goto err_free_pixmap;
103 
104     if (!ms_exa_set_pixmap_bo(scrn, pixmap, bo, TRUE))
105         goto err_free_bo;
106 
107     return pixmap;
108 err_free_bo:
109     dumb_bo_destroy(ms->drmmode.fd, bo);
110 err_free_pixmap:
111     screen->DestroyPixmap(pixmap);
112     return NULL;
113 }
114 
115 static int
ms_exa_egl_fd_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)116 ms_exa_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
117                           CARD16 *stride, CARD32 *size)
118 {
119     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
120     modesettingPtr ms = modesettingPTR(scrn);
121 	struct dumb_bo *bo;
122 	int fd;
123 
124     bo = ms_exa_bo_from_pixmap(screen, pixmap);
125     if (!bo)
126         return -1;
127 
128     fd = dumb_bo_get_fd(ms->drmmode.fd, bo, 0);
129     *stride = bo->pitch;
130 	*size = bo->size;
131 
132     return fd;
133 }
134 
135 static int
ms_exa_egl_fds_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,int * fds,uint32_t * strides,uint32_t * offsets,uint64_t * modifier)136 ms_exa_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
137                            uint32_t *strides, uint32_t *offsets,
138                            uint64_t *modifier)
139 {
140     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
141     modesettingPtr ms = modesettingPTR(scrn);
142 	struct dumb_bo *bo;
143 
144     bo = ms_exa_bo_from_pixmap(screen, pixmap);
145     if (!bo)
146         return 0;
147 
148     fds[0] = dumb_bo_get_fd(ms->drmmode.fd, bo, 0);
149     strides[0] = bo->pitch;
150     offsets[0] = 0;
151     *modifier = DRM_FORMAT_MOD_INVALID;
152 
153     return 1;
154 }
155 
156 static Bool
ms_exa_get_formats(ScreenPtr screen,CARD32 * num_formats,CARD32 ** formats)157 ms_exa_get_formats(ScreenPtr screen,
158 				   CARD32 *num_formats, CARD32 **formats)
159 {
160 	/* TODO: Return formats */
161     *num_formats = 0;
162     return TRUE;
163 }
164 
165 static Bool
ms_exa_get_modifiers(ScreenPtr screen,uint32_t format,uint32_t * num_modifiers,uint64_t ** modifiers)166 ms_exa_get_modifiers(ScreenPtr screen, uint32_t format,
167                      uint32_t *num_modifiers, uint64_t **modifiers)
168 {
169     *num_modifiers = 0;
170     return TRUE;
171 }
172 
173 static Bool
ms_exa_get_drawable_modifiers(DrawablePtr draw,uint32_t format,uint32_t * num_modifiers,uint64_t ** modifiers)174 ms_exa_get_drawable_modifiers(DrawablePtr draw, uint32_t format,
175                               uint32_t *num_modifiers, uint64_t **modifiers)
176 {
177     *num_modifiers = 0;
178     return TRUE;
179 }
180 
181 static const dri3_screen_info_rec ms_exa_dri3_info = {
182     .version = 2,
183     .open_client = ms_exa_dri3_open_client,
184     .pixmap_from_fds = ms_exa_pixmap_from_fds,
185     .fd_from_pixmap = ms_exa_egl_fd_from_pixmap,
186     .fds_from_pixmap = ms_exa_egl_fds_from_pixmap,
187     .get_formats = ms_exa_get_formats,
188     .get_modifiers = ms_exa_get_modifiers,
189     .get_drawable_modifiers = ms_exa_get_drawable_modifiers,
190 };
191 
192 Bool
ms_exa_dri3_init(ScreenPtr screen)193 ms_exa_dri3_init(ScreenPtr screen)
194 {
195     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
196     modesettingPtr ms = modesettingPTR(scrn);
197     ms->drmmode.dri3_device_name = drmGetDeviceNameFromFd2(ms->drmmode.fd);
198 
199 	return dri3_screen_init(screen, &ms_exa_dri3_info);
200 }
201