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