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 <syncsrv.h>
29*4882a593Smuzhiyun #include <unistd.h>
30*4882a593Smuzhiyun #include <xace.h>
31*4882a593Smuzhiyun #include "../Xext/syncsdk.h"
32*4882a593Smuzhiyun #include <protocol-versions.h>
33*4882a593Smuzhiyun #include <drm_fourcc.h>
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun static Bool
dri3_screen_can_one_point_two(ScreenPtr screen)36*4882a593Smuzhiyun dri3_screen_can_one_point_two(ScreenPtr screen)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun dri3_screen_priv_ptr dri3 = dri3_screen_priv(screen);
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun if (dri3 && dri3->info && dri3->info->version >= 2 &&
41*4882a593Smuzhiyun dri3->info->pixmap_from_fds && dri3->info->fds_from_pixmap &&
42*4882a593Smuzhiyun dri3->info->get_formats && dri3->info->get_modifiers &&
43*4882a593Smuzhiyun dri3->info->get_drawable_modifiers)
44*4882a593Smuzhiyun return TRUE;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun return FALSE;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun static int
proc_dri3_query_version(ClientPtr client)50*4882a593Smuzhiyun proc_dri3_query_version(ClientPtr client)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun REQUEST(xDRI3QueryVersionReq);
53*4882a593Smuzhiyun xDRI3QueryVersionReply rep = {
54*4882a593Smuzhiyun .type = X_Reply,
55*4882a593Smuzhiyun .sequenceNumber = client->sequence,
56*4882a593Smuzhiyun .length = 0,
57*4882a593Smuzhiyun .majorVersion = SERVER_DRI3_MAJOR_VERSION,
58*4882a593Smuzhiyun .minorVersion = SERVER_DRI3_MINOR_VERSION
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun for (int i = 0; i < screenInfo.numScreens; i++) {
64*4882a593Smuzhiyun if (!dri3_screen_can_one_point_two(screenInfo.screens[i])) {
65*4882a593Smuzhiyun rep.minorVersion = 0;
66*4882a593Smuzhiyun break;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun for (int i = 0; i < screenInfo.numGPUScreens; i++) {
71*4882a593Smuzhiyun if (!dri3_screen_can_one_point_two(screenInfo.gpuscreens[i])) {
72*4882a593Smuzhiyun rep.minorVersion = 0;
73*4882a593Smuzhiyun break;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /* From DRI3 proto:
78*4882a593Smuzhiyun *
79*4882a593Smuzhiyun * The client sends the highest supported version to the server
80*4882a593Smuzhiyun * and the server sends the highest version it supports, but no
81*4882a593Smuzhiyun * higher than the requested version.
82*4882a593Smuzhiyun */
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (rep.majorVersion > stuff->majorVersion ||
85*4882a593Smuzhiyun (rep.majorVersion == stuff->majorVersion &&
86*4882a593Smuzhiyun rep.minorVersion > stuff->minorVersion)) {
87*4882a593Smuzhiyun rep.majorVersion = stuff->majorVersion;
88*4882a593Smuzhiyun rep.minorVersion = stuff->minorVersion;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun if (client->swapped) {
92*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
93*4882a593Smuzhiyun swapl(&rep.length);
94*4882a593Smuzhiyun swapl(&rep.majorVersion);
95*4882a593Smuzhiyun swapl(&rep.minorVersion);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun WriteToClient(client, sizeof(rep), &rep);
98*4882a593Smuzhiyun return Success;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun int
dri3_send_open_reply(ClientPtr client,int fd)102*4882a593Smuzhiyun dri3_send_open_reply(ClientPtr client, int fd)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun xDRI3OpenReply rep = {
105*4882a593Smuzhiyun .type = X_Reply,
106*4882a593Smuzhiyun .nfd = 1,
107*4882a593Smuzhiyun .sequenceNumber = client->sequence,
108*4882a593Smuzhiyun .length = 0,
109*4882a593Smuzhiyun };
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun if (client->swapped) {
112*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
113*4882a593Smuzhiyun swapl(&rep.length);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (WriteFdToClient(client, fd, TRUE) < 0) {
117*4882a593Smuzhiyun close(fd);
118*4882a593Smuzhiyun return BadAlloc;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun WriteToClient(client, sizeof (rep), &rep);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun return Success;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun static int
proc_dri3_open(ClientPtr client)127*4882a593Smuzhiyun proc_dri3_open(ClientPtr client)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun REQUEST(xDRI3OpenReq);
130*4882a593Smuzhiyun RRProviderPtr provider;
131*4882a593Smuzhiyun DrawablePtr drawable;
132*4882a593Smuzhiyun ScreenPtr screen;
133*4882a593Smuzhiyun int fd;
134*4882a593Smuzhiyun int status;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3OpenReq);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess);
139*4882a593Smuzhiyun if (status != Success)
140*4882a593Smuzhiyun return status;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun if (stuff->provider == None)
143*4882a593Smuzhiyun provider = NULL;
144*4882a593Smuzhiyun else if (!RRProviderType) {
145*4882a593Smuzhiyun return BadMatch;
146*4882a593Smuzhiyun } else {
147*4882a593Smuzhiyun VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
148*4882a593Smuzhiyun if (drawable->pScreen != provider->pScreen)
149*4882a593Smuzhiyun return BadMatch;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun screen = drawable->pScreen;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun status = dri3_open(client, screen, provider, &fd);
154*4882a593Smuzhiyun if (status != Success)
155*4882a593Smuzhiyun return status;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if (client->ignoreCount == 0)
158*4882a593Smuzhiyun return dri3_send_open_reply(client, fd);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun return Success;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun static int
proc_dri3_pixmap_from_buffer(ClientPtr client)164*4882a593Smuzhiyun proc_dri3_pixmap_from_buffer(ClientPtr client)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun REQUEST(xDRI3PixmapFromBufferReq);
167*4882a593Smuzhiyun int fd;
168*4882a593Smuzhiyun DrawablePtr drawable;
169*4882a593Smuzhiyun PixmapPtr pixmap;
170*4882a593Smuzhiyun CARD32 stride, offset;
171*4882a593Smuzhiyun int rc;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun SetReqFds(client, 1);
174*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
175*4882a593Smuzhiyun LEGAL_NEW_RESOURCE(stuff->pixmap, client);
176*4882a593Smuzhiyun rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
177*4882a593Smuzhiyun if (rc != Success) {
178*4882a593Smuzhiyun client->errorValue = stuff->drawable;
179*4882a593Smuzhiyun return rc;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if (!stuff->width || !stuff->height) {
183*4882a593Smuzhiyun client->errorValue = 0;
184*4882a593Smuzhiyun return BadValue;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (stuff->width > 32767 || stuff->height > 32767)
188*4882a593Smuzhiyun return BadAlloc;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if (stuff->depth != 1) {
191*4882a593Smuzhiyun DepthPtr depth = drawable->pScreen->allowedDepths;
192*4882a593Smuzhiyun int i;
193*4882a593Smuzhiyun for (i = 0; i < drawable->pScreen->numDepths; i++, depth++)
194*4882a593Smuzhiyun if (depth->depth == stuff->depth)
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun if (i == drawable->pScreen->numDepths) {
197*4882a593Smuzhiyun client->errorValue = stuff->depth;
198*4882a593Smuzhiyun return BadValue;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun fd = ReadFdFromClient(client);
203*4882a593Smuzhiyun if (fd < 0)
204*4882a593Smuzhiyun return BadValue;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun offset = 0;
207*4882a593Smuzhiyun stride = stuff->stride;
208*4882a593Smuzhiyun rc = dri3_pixmap_from_fds(&pixmap,
209*4882a593Smuzhiyun drawable->pScreen, 1, &fd,
210*4882a593Smuzhiyun stuff->width, stuff->height,
211*4882a593Smuzhiyun &stride, &offset,
212*4882a593Smuzhiyun stuff->depth, stuff->bpp,
213*4882a593Smuzhiyun DRM_FORMAT_MOD_INVALID);
214*4882a593Smuzhiyun close (fd);
215*4882a593Smuzhiyun if (rc != Success)
216*4882a593Smuzhiyun return rc;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun pixmap->drawable.id = stuff->pixmap;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /* security creation/labeling check */
221*4882a593Smuzhiyun rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
222*4882a593Smuzhiyun pixmap, RT_NONE, NULL, DixCreateAccess);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun if (rc != Success) {
225*4882a593Smuzhiyun (*drawable->pScreen->DestroyPixmap) (pixmap);
226*4882a593Smuzhiyun return rc;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap))
229*4882a593Smuzhiyun return BadAlloc;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun return Success;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun static int
proc_dri3_buffer_from_pixmap(ClientPtr client)235*4882a593Smuzhiyun proc_dri3_buffer_from_pixmap(ClientPtr client)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun REQUEST(xDRI3BufferFromPixmapReq);
238*4882a593Smuzhiyun xDRI3BufferFromPixmapReply rep = {
239*4882a593Smuzhiyun .type = X_Reply,
240*4882a593Smuzhiyun .nfd = 1,
241*4882a593Smuzhiyun .sequenceNumber = client->sequence,
242*4882a593Smuzhiyun .length = 0,
243*4882a593Smuzhiyun };
244*4882a593Smuzhiyun int rc;
245*4882a593Smuzhiyun int fd;
246*4882a593Smuzhiyun PixmapPtr pixmap;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
249*4882a593Smuzhiyun rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP,
250*4882a593Smuzhiyun client, DixWriteAccess);
251*4882a593Smuzhiyun if (rc != Success) {
252*4882a593Smuzhiyun client->errorValue = stuff->pixmap;
253*4882a593Smuzhiyun return rc;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun rep.width = pixmap->drawable.width;
257*4882a593Smuzhiyun rep.height = pixmap->drawable.height;
258*4882a593Smuzhiyun rep.depth = pixmap->drawable.depth;
259*4882a593Smuzhiyun rep.bpp = pixmap->drawable.bitsPerPixel;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun fd = dri3_fd_from_pixmap(pixmap, &rep.stride, &rep.size);
262*4882a593Smuzhiyun if (fd < 0)
263*4882a593Smuzhiyun return BadPixmap;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun if (client->swapped) {
266*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
267*4882a593Smuzhiyun swapl(&rep.length);
268*4882a593Smuzhiyun swapl(&rep.size);
269*4882a593Smuzhiyun swaps(&rep.width);
270*4882a593Smuzhiyun swaps(&rep.height);
271*4882a593Smuzhiyun swaps(&rep.stride);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun if (WriteFdToClient(client, fd, TRUE) < 0) {
274*4882a593Smuzhiyun close(fd);
275*4882a593Smuzhiyun return BadAlloc;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun WriteToClient(client, sizeof(rep), &rep);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun return Success;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun static int
proc_dri3_fence_from_fd(ClientPtr client)284*4882a593Smuzhiyun proc_dri3_fence_from_fd(ClientPtr client)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun REQUEST(xDRI3FenceFromFDReq);
287*4882a593Smuzhiyun DrawablePtr drawable;
288*4882a593Smuzhiyun int fd;
289*4882a593Smuzhiyun int status;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun SetReqFds(client, 1);
292*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
293*4882a593Smuzhiyun LEGAL_NEW_RESOURCE(stuff->fence, client);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
296*4882a593Smuzhiyun if (status != Success)
297*4882a593Smuzhiyun return status;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun fd = ReadFdFromClient(client);
300*4882a593Smuzhiyun if (fd < 0)
301*4882a593Smuzhiyun return BadValue;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun status = SyncCreateFenceFromFD(client, drawable, stuff->fence,
304*4882a593Smuzhiyun fd, stuff->initially_triggered);
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun return status;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun static int
proc_dri3_fd_from_fence(ClientPtr client)310*4882a593Smuzhiyun proc_dri3_fd_from_fence(ClientPtr client)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun REQUEST(xDRI3FDFromFenceReq);
313*4882a593Smuzhiyun xDRI3FDFromFenceReply rep = {
314*4882a593Smuzhiyun .type = X_Reply,
315*4882a593Smuzhiyun .nfd = 1,
316*4882a593Smuzhiyun .sequenceNumber = client->sequence,
317*4882a593Smuzhiyun .length = 0,
318*4882a593Smuzhiyun };
319*4882a593Smuzhiyun DrawablePtr drawable;
320*4882a593Smuzhiyun int fd;
321*4882a593Smuzhiyun int status;
322*4882a593Smuzhiyun SyncFence *fence;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
327*4882a593Smuzhiyun if (status != Success)
328*4882a593Smuzhiyun return status;
329*4882a593Smuzhiyun status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess);
330*4882a593Smuzhiyun if (status != Success)
331*4882a593Smuzhiyun return status;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun fd = SyncFDFromFence(client, drawable, fence);
334*4882a593Smuzhiyun if (fd < 0)
335*4882a593Smuzhiyun return BadMatch;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun if (client->swapped) {
338*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
339*4882a593Smuzhiyun swapl(&rep.length);
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun if (WriteFdToClient(client, fd, FALSE) < 0)
342*4882a593Smuzhiyun return BadAlloc;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun WriteToClient(client, sizeof(rep), &rep);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun return Success;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun static int
proc_dri3_get_supported_modifiers(ClientPtr client)350*4882a593Smuzhiyun proc_dri3_get_supported_modifiers(ClientPtr client)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun REQUEST(xDRI3GetSupportedModifiersReq);
353*4882a593Smuzhiyun xDRI3GetSupportedModifiersReply rep = {
354*4882a593Smuzhiyun .type = X_Reply,
355*4882a593Smuzhiyun .sequenceNumber = client->sequence,
356*4882a593Smuzhiyun };
357*4882a593Smuzhiyun WindowPtr window;
358*4882a593Smuzhiyun ScreenPtr pScreen;
359*4882a593Smuzhiyun CARD64 *window_modifiers = NULL;
360*4882a593Smuzhiyun CARD64 *screen_modifiers = NULL;
361*4882a593Smuzhiyun CARD32 nwindowmodifiers = 0;
362*4882a593Smuzhiyun CARD32 nscreenmodifiers = 0;
363*4882a593Smuzhiyun int status;
364*4882a593Smuzhiyun int i;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun status = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
369*4882a593Smuzhiyun if (status != Success)
370*4882a593Smuzhiyun return status;
371*4882a593Smuzhiyun pScreen = window->drawable.pScreen;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun dri3_get_supported_modifiers(pScreen, &window->drawable,
374*4882a593Smuzhiyun stuff->depth, stuff->bpp,
375*4882a593Smuzhiyun &nwindowmodifiers, &window_modifiers,
376*4882a593Smuzhiyun &nscreenmodifiers, &screen_modifiers);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun rep.numWindowModifiers = nwindowmodifiers;
379*4882a593Smuzhiyun rep.numScreenModifiers = nscreenmodifiers;
380*4882a593Smuzhiyun rep.length = bytes_to_int32(rep.numWindowModifiers * sizeof(CARD64)) +
381*4882a593Smuzhiyun bytes_to_int32(rep.numScreenModifiers * sizeof(CARD64));
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (client->swapped) {
384*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
385*4882a593Smuzhiyun swapl(&rep.length);
386*4882a593Smuzhiyun swapl(&rep.numWindowModifiers);
387*4882a593Smuzhiyun swapl(&rep.numScreenModifiers);
388*4882a593Smuzhiyun for (i = 0; i < nwindowmodifiers; i++)
389*4882a593Smuzhiyun swapll(&window_modifiers[i]);
390*4882a593Smuzhiyun for (i = 0; i < nscreenmodifiers; i++)
391*4882a593Smuzhiyun swapll(&screen_modifiers[i]);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun WriteToClient(client, sizeof(rep), &rep);
395*4882a593Smuzhiyun WriteToClient(client, nwindowmodifiers * sizeof(CARD64), window_modifiers);
396*4882a593Smuzhiyun WriteToClient(client, nscreenmodifiers * sizeof(CARD64), screen_modifiers);
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun free(window_modifiers);
399*4882a593Smuzhiyun free(screen_modifiers);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun return Success;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun static int
proc_dri3_pixmap_from_buffers(ClientPtr client)405*4882a593Smuzhiyun proc_dri3_pixmap_from_buffers(ClientPtr client)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun REQUEST(xDRI3PixmapFromBuffersReq);
408*4882a593Smuzhiyun int fds[4];
409*4882a593Smuzhiyun CARD32 strides[4], offsets[4];
410*4882a593Smuzhiyun ScreenPtr screen;
411*4882a593Smuzhiyun WindowPtr window;
412*4882a593Smuzhiyun PixmapPtr pixmap;
413*4882a593Smuzhiyun int rc;
414*4882a593Smuzhiyun int i;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun SetReqFds(client, stuff->num_buffers);
417*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq);
418*4882a593Smuzhiyun LEGAL_NEW_RESOURCE(stuff->pixmap, client);
419*4882a593Smuzhiyun rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
420*4882a593Smuzhiyun if (rc != Success) {
421*4882a593Smuzhiyun client->errorValue = stuff->window;
422*4882a593Smuzhiyun return rc;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun screen = window->drawable.pScreen;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (!stuff->width || !stuff->height || !stuff->bpp || !stuff->depth) {
427*4882a593Smuzhiyun client->errorValue = 0;
428*4882a593Smuzhiyun return BadValue;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun if (stuff->width > 32767 || stuff->height > 32767)
432*4882a593Smuzhiyun return BadAlloc;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun if (stuff->depth != 1) {
435*4882a593Smuzhiyun DepthPtr depth = screen->allowedDepths;
436*4882a593Smuzhiyun int j;
437*4882a593Smuzhiyun for (j = 0; j < screen->numDepths; j++, depth++)
438*4882a593Smuzhiyun if (depth->depth == stuff->depth)
439*4882a593Smuzhiyun break;
440*4882a593Smuzhiyun if (j == screen->numDepths) {
441*4882a593Smuzhiyun client->errorValue = stuff->depth;
442*4882a593Smuzhiyun return BadValue;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun if (!stuff->num_buffers || stuff->num_buffers > 4) {
447*4882a593Smuzhiyun client->errorValue = stuff->num_buffers;
448*4882a593Smuzhiyun return BadValue;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun for (i = 0; i < stuff->num_buffers; i++) {
452*4882a593Smuzhiyun fds[i] = ReadFdFromClient(client);
453*4882a593Smuzhiyun if (fds[i] < 0) {
454*4882a593Smuzhiyun while (--i >= 0)
455*4882a593Smuzhiyun close(fds[i]);
456*4882a593Smuzhiyun return BadValue;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun strides[0] = stuff->stride0;
461*4882a593Smuzhiyun strides[1] = stuff->stride1;
462*4882a593Smuzhiyun strides[2] = stuff->stride2;
463*4882a593Smuzhiyun strides[3] = stuff->stride3;
464*4882a593Smuzhiyun offsets[0] = stuff->offset0;
465*4882a593Smuzhiyun offsets[1] = stuff->offset1;
466*4882a593Smuzhiyun offsets[2] = stuff->offset2;
467*4882a593Smuzhiyun offsets[3] = stuff->offset3;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun rc = dri3_pixmap_from_fds(&pixmap, screen,
470*4882a593Smuzhiyun stuff->num_buffers, fds,
471*4882a593Smuzhiyun stuff->width, stuff->height,
472*4882a593Smuzhiyun strides, offsets,
473*4882a593Smuzhiyun stuff->depth, stuff->bpp,
474*4882a593Smuzhiyun stuff->modifier);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun for (i = 0; i < stuff->num_buffers; i++)
477*4882a593Smuzhiyun close (fds[i]);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (rc != Success)
480*4882a593Smuzhiyun return rc;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun pixmap->drawable.id = stuff->pixmap;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun /* security creation/labeling check */
485*4882a593Smuzhiyun rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
486*4882a593Smuzhiyun pixmap, RT_NONE, NULL, DixCreateAccess);
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun if (rc != Success) {
489*4882a593Smuzhiyun (*screen->DestroyPixmap) (pixmap);
490*4882a593Smuzhiyun return rc;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap))
493*4882a593Smuzhiyun return BadAlloc;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun return Success;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun static int
proc_dri3_buffers_from_pixmap(ClientPtr client)499*4882a593Smuzhiyun proc_dri3_buffers_from_pixmap(ClientPtr client)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun REQUEST(xDRI3BuffersFromPixmapReq);
502*4882a593Smuzhiyun xDRI3BuffersFromPixmapReply rep = {
503*4882a593Smuzhiyun .type = X_Reply,
504*4882a593Smuzhiyun .sequenceNumber = client->sequence,
505*4882a593Smuzhiyun };
506*4882a593Smuzhiyun int rc;
507*4882a593Smuzhiyun int fds[4];
508*4882a593Smuzhiyun int num_fds;
509*4882a593Smuzhiyun uint32_t strides[4], offsets[4];
510*4882a593Smuzhiyun uint64_t modifier;
511*4882a593Smuzhiyun int i;
512*4882a593Smuzhiyun PixmapPtr pixmap;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq);
515*4882a593Smuzhiyun rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP,
516*4882a593Smuzhiyun client, DixWriteAccess);
517*4882a593Smuzhiyun if (rc != Success) {
518*4882a593Smuzhiyun client->errorValue = stuff->pixmap;
519*4882a593Smuzhiyun return rc;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier);
523*4882a593Smuzhiyun if (num_fds == 0)
524*4882a593Smuzhiyun return BadPixmap;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun rep.nfd = num_fds;
527*4882a593Smuzhiyun rep.length = bytes_to_int32(num_fds * 2 * sizeof(CARD32));
528*4882a593Smuzhiyun rep.width = pixmap->drawable.width;
529*4882a593Smuzhiyun rep.height = pixmap->drawable.height;
530*4882a593Smuzhiyun rep.depth = pixmap->drawable.depth;
531*4882a593Smuzhiyun rep.bpp = pixmap->drawable.bitsPerPixel;
532*4882a593Smuzhiyun rep.modifier = modifier;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun if (client->swapped) {
535*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
536*4882a593Smuzhiyun swapl(&rep.length);
537*4882a593Smuzhiyun swaps(&rep.width);
538*4882a593Smuzhiyun swaps(&rep.height);
539*4882a593Smuzhiyun swapll(&rep.modifier);
540*4882a593Smuzhiyun for (i = 0; i < num_fds; i++) {
541*4882a593Smuzhiyun swapl(&strides[i]);
542*4882a593Smuzhiyun swapl(&offsets[i]);
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun for (i = 0; i < num_fds; i++) {
547*4882a593Smuzhiyun if (WriteFdToClient(client, fds[i], TRUE) < 0) {
548*4882a593Smuzhiyun while (i--)
549*4882a593Smuzhiyun close(fds[i]);
550*4882a593Smuzhiyun return BadAlloc;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun WriteToClient(client, sizeof(rep), &rep);
555*4882a593Smuzhiyun WriteToClient(client, num_fds * sizeof(CARD32), strides);
556*4882a593Smuzhiyun WriteToClient(client, num_fds * sizeof(CARD32), offsets);
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun return Success;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
562*4882a593Smuzhiyun proc_dri3_query_version, /* 0 */
563*4882a593Smuzhiyun proc_dri3_open, /* 1 */
564*4882a593Smuzhiyun proc_dri3_pixmap_from_buffer, /* 2 */
565*4882a593Smuzhiyun proc_dri3_buffer_from_pixmap, /* 3 */
566*4882a593Smuzhiyun proc_dri3_fence_from_fd, /* 4 */
567*4882a593Smuzhiyun proc_dri3_fd_from_fence, /* 5 */
568*4882a593Smuzhiyun proc_dri3_get_supported_modifiers, /* 6 */
569*4882a593Smuzhiyun proc_dri3_pixmap_from_buffers, /* 7 */
570*4882a593Smuzhiyun proc_dri3_buffers_from_pixmap, /* 8 */
571*4882a593Smuzhiyun };
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun int
proc_dri3_dispatch(ClientPtr client)574*4882a593Smuzhiyun proc_dri3_dispatch(ClientPtr client)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun REQUEST(xReq);
577*4882a593Smuzhiyun if (!client->local)
578*4882a593Smuzhiyun return BadMatch;
579*4882a593Smuzhiyun if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data])
580*4882a593Smuzhiyun return BadRequest;
581*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->data]) (client);
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_query_version(ClientPtr client)585*4882a593Smuzhiyun sproc_dri3_query_version(ClientPtr client)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun REQUEST(xDRI3QueryVersionReq);
588*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun swaps(&stuff->length);
591*4882a593Smuzhiyun swapl(&stuff->majorVersion);
592*4882a593Smuzhiyun swapl(&stuff->minorVersion);
593*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_open(ClientPtr client)597*4882a593Smuzhiyun sproc_dri3_open(ClientPtr client)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun REQUEST(xDRI3OpenReq);
600*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3OpenReq);
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun swaps(&stuff->length);
603*4882a593Smuzhiyun swapl(&stuff->drawable);
604*4882a593Smuzhiyun swapl(&stuff->provider);
605*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_pixmap_from_buffer(ClientPtr client)609*4882a593Smuzhiyun sproc_dri3_pixmap_from_buffer(ClientPtr client)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun REQUEST(xDRI3PixmapFromBufferReq);
612*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun swaps(&stuff->length);
615*4882a593Smuzhiyun swapl(&stuff->pixmap);
616*4882a593Smuzhiyun swapl(&stuff->drawable);
617*4882a593Smuzhiyun swapl(&stuff->size);
618*4882a593Smuzhiyun swaps(&stuff->width);
619*4882a593Smuzhiyun swaps(&stuff->height);
620*4882a593Smuzhiyun swaps(&stuff->stride);
621*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_buffer_from_pixmap(ClientPtr client)625*4882a593Smuzhiyun sproc_dri3_buffer_from_pixmap(ClientPtr client)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun REQUEST(xDRI3BufferFromPixmapReq);
628*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun swaps(&stuff->length);
631*4882a593Smuzhiyun swapl(&stuff->pixmap);
632*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_fence_from_fd(ClientPtr client)636*4882a593Smuzhiyun sproc_dri3_fence_from_fd(ClientPtr client)
637*4882a593Smuzhiyun {
638*4882a593Smuzhiyun REQUEST(xDRI3FenceFromFDReq);
639*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun swaps(&stuff->length);
642*4882a593Smuzhiyun swapl(&stuff->drawable);
643*4882a593Smuzhiyun swapl(&stuff->fence);
644*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_fd_from_fence(ClientPtr client)648*4882a593Smuzhiyun sproc_dri3_fd_from_fence(ClientPtr client)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun REQUEST(xDRI3FDFromFenceReq);
651*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun swaps(&stuff->length);
654*4882a593Smuzhiyun swapl(&stuff->drawable);
655*4882a593Smuzhiyun swapl(&stuff->fence);
656*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_get_supported_modifiers(ClientPtr client)660*4882a593Smuzhiyun sproc_dri3_get_supported_modifiers(ClientPtr client)
661*4882a593Smuzhiyun {
662*4882a593Smuzhiyun REQUEST(xDRI3GetSupportedModifiersReq);
663*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq);
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun swaps(&stuff->length);
666*4882a593Smuzhiyun swapl(&stuff->window);
667*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_pixmap_from_buffers(ClientPtr client)671*4882a593Smuzhiyun sproc_dri3_pixmap_from_buffers(ClientPtr client)
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun REQUEST(xDRI3PixmapFromBuffersReq);
674*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq);
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun swaps(&stuff->length);
677*4882a593Smuzhiyun swapl(&stuff->pixmap);
678*4882a593Smuzhiyun swapl(&stuff->window);
679*4882a593Smuzhiyun swaps(&stuff->width);
680*4882a593Smuzhiyun swaps(&stuff->height);
681*4882a593Smuzhiyun swapl(&stuff->stride0);
682*4882a593Smuzhiyun swapl(&stuff->offset0);
683*4882a593Smuzhiyun swapl(&stuff->stride1);
684*4882a593Smuzhiyun swapl(&stuff->offset1);
685*4882a593Smuzhiyun swapl(&stuff->stride2);
686*4882a593Smuzhiyun swapl(&stuff->offset2);
687*4882a593Smuzhiyun swapl(&stuff->stride3);
688*4882a593Smuzhiyun swapl(&stuff->offset3);
689*4882a593Smuzhiyun swapll(&stuff->modifier);
690*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun static int _X_COLD
sproc_dri3_buffers_from_pixmap(ClientPtr client)694*4882a593Smuzhiyun sproc_dri3_buffers_from_pixmap(ClientPtr client)
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun REQUEST(xDRI3BuffersFromPixmapReq);
697*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq);
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun swaps(&stuff->length);
700*4882a593Smuzhiyun swapl(&stuff->pixmap);
701*4882a593Smuzhiyun return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
705*4882a593Smuzhiyun sproc_dri3_query_version, /* 0 */
706*4882a593Smuzhiyun sproc_dri3_open, /* 1 */
707*4882a593Smuzhiyun sproc_dri3_pixmap_from_buffer, /* 2 */
708*4882a593Smuzhiyun sproc_dri3_buffer_from_pixmap, /* 3 */
709*4882a593Smuzhiyun sproc_dri3_fence_from_fd, /* 4 */
710*4882a593Smuzhiyun sproc_dri3_fd_from_fence, /* 5 */
711*4882a593Smuzhiyun sproc_dri3_get_supported_modifiers, /* 6 */
712*4882a593Smuzhiyun sproc_dri3_pixmap_from_buffers, /* 7 */
713*4882a593Smuzhiyun sproc_dri3_buffers_from_pixmap, /* 8 */
714*4882a593Smuzhiyun };
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun int _X_COLD
sproc_dri3_dispatch(ClientPtr client)717*4882a593Smuzhiyun sproc_dri3_dispatch(ClientPtr client)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun REQUEST(xReq);
720*4882a593Smuzhiyun if (!client->local)
721*4882a593Smuzhiyun return BadMatch;
722*4882a593Smuzhiyun if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data])
723*4882a593Smuzhiyun return BadRequest;
724*4882a593Smuzhiyun return (*sproc_dri3_vector[stuff->data]) (client);
725*4882a593Smuzhiyun }
726