Add patch that contain Mali fixes.
[deb_xorg-server.git] / dri3 / dri3_request.c
CommitLineData
a09e091a
JB
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#ifdef HAVE_XORG_CONFIG_H
24#include <xorg-config.h>
25#endif
26
27#include "dri3_priv.h"
28#include <syncsrv.h>
29#include <unistd.h>
30#include <xace.h>
31#include "../Xext/syncsdk.h"
32#include <protocol-versions.h>
33
34static int
35proc_dri3_query_version(ClientPtr client)
36{
37 REQUEST(xDRI3QueryVersionReq);
38 xDRI3QueryVersionReply rep = {
39 .type = X_Reply,
40 .sequenceNumber = client->sequence,
41 .length = 0,
42 .majorVersion = SERVER_DRI3_MAJOR_VERSION,
43 .minorVersion = SERVER_DRI3_MINOR_VERSION
44 };
45
46 REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
47 (void) stuff;
48 if (client->swapped) {
49 swaps(&rep.sequenceNumber);
50 swapl(&rep.length);
51 swapl(&rep.majorVersion);
52 swapl(&rep.minorVersion);
53 }
54 WriteToClient(client, sizeof(rep), &rep);
55 return Success;
56}
57
58static int
59proc_dri3_open(ClientPtr client)
60{
61 REQUEST(xDRI3OpenReq);
62 xDRI3OpenReply rep = {
63 .type = X_Reply,
64 .nfd = 1,
65 .sequenceNumber = client->sequence,
66 .length = 0,
67 };
68 RRProviderPtr provider;
69 DrawablePtr drawable;
70 ScreenPtr screen;
71 int fd;
72 int status;
73
74 REQUEST_SIZE_MATCH(xDRI3OpenReq);
75
76 status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess);
77 if (status != Success)
78 return status;
79
80 if (stuff->provider == None)
81 provider = NULL;
82 else if (!RRProviderType) {
83 return BadMatch;
84 } else {
85 VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
86 if (drawable->pScreen != provider->pScreen)
87 return BadMatch;
88 }
89 screen = drawable->pScreen;
90
91 status = dri3_open(client, screen, provider, &fd);
92 if (status != Success)
93 return status;
94
95 if (client->swapped) {
96 swaps(&rep.sequenceNumber);
97 swapl(&rep.length);
98 }
99
100 if (WriteFdToClient(client, fd, TRUE) < 0) {
101 close(fd);
102 return BadAlloc;
103 }
104
105 WriteToClient(client, sizeof (rep), &rep);
106
107 return Success;
108}
109
110static int
111proc_dri3_pixmap_from_buffer(ClientPtr client)
112{
113 REQUEST(xDRI3PixmapFromBufferReq);
114 int fd;
115 DrawablePtr drawable;
116 PixmapPtr pixmap;
117 int rc;
118
119 SetReqFds(client, 1);
120 REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
121 LEGAL_NEW_RESOURCE(stuff->pixmap, client);
122 rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
123 if (rc != Success) {
124 client->errorValue = stuff->drawable;
125 return rc;
126 }
127
128 if (!stuff->width || !stuff->height) {
129 client->errorValue = 0;
130 return BadValue;
131 }
132
133 if (stuff->width > 32767 || stuff->height > 32767)
134 return BadAlloc;
135
136 if (stuff->depth != 1) {
137 DepthPtr depth = drawable->pScreen->allowedDepths;
138 int i;
139 for (i = 0; i < drawable->pScreen->numDepths; i++, depth++)
140 if (depth->depth == stuff->depth)
141 break;
142 if (i == drawable->pScreen->numDepths) {
143 client->errorValue = stuff->depth;
144 return BadValue;
145 }
146 }
147
148 fd = ReadFdFromClient(client);
149 if (fd < 0)
150 return BadValue;
151
152 rc = dri3_pixmap_from_fd(&pixmap,
153 drawable->pScreen, fd,
154 stuff->width, stuff->height,
155 stuff->stride, stuff->depth,
156 stuff->bpp);
157 close (fd);
158 if (rc != Success)
159 return rc;
160
161 pixmap->drawable.id = stuff->pixmap;
162
163 /* security creation/labeling check */
164 rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
165 pixmap, RT_NONE, NULL, DixCreateAccess);
166
167 if (rc != Success) {
168 (*drawable->pScreen->DestroyPixmap) (pixmap);
169 return rc;
170 }
171 if (AddResource(stuff->pixmap, RT_PIXMAP, (pointer) pixmap))
172 return Success;
173
174 return Success;
175}
176
177static int
178proc_dri3_buffer_from_pixmap(ClientPtr client)
179{
180 REQUEST(xDRI3BufferFromPixmapReq);
181 xDRI3BufferFromPixmapReply rep = {
182 .type = X_Reply,
183 .nfd = 1,
184 .sequenceNumber = client->sequence,
185 .length = 0,
186 };
187 int rc;
188 int fd;
189 PixmapPtr pixmap;
190
191 REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
192 rc = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP,
193 client, DixWriteAccess);
194 if (rc != Success) {
195 client->errorValue = stuff->pixmap;
196 return rc;
197 }
198
199 rep.width = pixmap->drawable.width;
200 rep.height = pixmap->drawable.height;
201 rep.depth = pixmap->drawable.depth;
202 rep.bpp = pixmap->drawable.bitsPerPixel;
203
204 rc = dri3_fd_from_pixmap(&fd, pixmap, &rep.stride, &rep.size);
205 if (rc != Success)
206 return rc;
207
208 if (client->swapped) {
209 swaps(&rep.sequenceNumber);
210 swapl(&rep.length);
211 swapl(&rep.size);
212 swaps(&rep.width);
213 swaps(&rep.height);
214 swaps(&rep.stride);
215 }
216 if (WriteFdToClient(client, fd, TRUE) < 0) {
217 close(fd);
218 return BadAlloc;
219 }
220
221 WriteToClient(client, sizeof(rep), &rep);
222
223 return client->noClientException;
224}
225
226static int
227proc_dri3_fence_from_fd(ClientPtr client)
228{
229 REQUEST(xDRI3FenceFromFDReq);
230 DrawablePtr drawable;
231 int fd;
232 int status;
233
234 SetReqFds(client, 1);
235 REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
236 LEGAL_NEW_RESOURCE(stuff->fence, client);
237
238 status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
239 if (status != Success)
240 return status;
241
242 fd = ReadFdFromClient(client);
243 if (fd < 0)
244 return BadValue;
245
246 status = SyncCreateFenceFromFD(client, drawable, stuff->fence,
247 fd, stuff->initially_triggered);
248
249 return status;
250}
251
252static int
253proc_dri3_fd_from_fence(ClientPtr client)
254{
255 REQUEST(xDRI3FDFromFenceReq);
256 xDRI3FDFromFenceReply rep = {
257 .type = X_Reply,
258 .nfd = 1,
259 .sequenceNumber = client->sequence,
260 .length = 0,
261 };
262 DrawablePtr drawable;
263 int fd;
264 int status;
265 SyncFence *fence;
266
267 REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
268
269 status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
270 if (status != Success)
271 return status;
272 status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess);
273 if (status != Success)
274 return status;
275
276 fd = SyncFDFromFence(client, drawable, fence);
277 if (fd < 0)
278 return BadMatch;
279
280 if (client->swapped) {
281 swaps(&rep.sequenceNumber);
282 swapl(&rep.length);
283 }
284 if (WriteFdToClient(client, fd, FALSE) < 0)
285 return BadAlloc;
286
287 WriteToClient(client, sizeof(rep), &rep);
288
289 return client->noClientException;
290}
291
292int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
293 proc_dri3_query_version, /* 0 */
294 proc_dri3_open, /* 1 */
295 proc_dri3_pixmap_from_buffer, /* 2 */
296 proc_dri3_buffer_from_pixmap, /* 3 */
297 proc_dri3_fence_from_fd, /* 4 */
298 proc_dri3_fd_from_fence, /* 5 */
299};
300
301int
302proc_dri3_dispatch(ClientPtr client)
303{
304 REQUEST(xReq);
305 if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data])
306 return BadRequest;
307 return (*proc_dri3_vector[stuff->data]) (client);
308}
309
310static int
311sproc_dri3_query_version(ClientPtr client)
312{
313 REQUEST(xDRI3QueryVersionReq);
314
315 swaps(&stuff->length);
316 swapl(&stuff->majorVersion);
317 swapl(&stuff->minorVersion);
318 return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
319}
320
321static int
322sproc_dri3_open(ClientPtr client)
323{
324 REQUEST(xDRI3OpenReq);
325
326 swaps(&stuff->length);
327 swapl(&stuff->drawable);
328 swapl(&stuff->provider);
329 return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
330}
331
332static int
333sproc_dri3_pixmap_from_buffer(ClientPtr client)
334{
335 REQUEST(xDRI3PixmapFromBufferReq);
336
337 swaps(&stuff->length);
338 swapl(&stuff->pixmap);
339 swapl(&stuff->drawable);
340 swapl(&stuff->size);
341 swaps(&stuff->width);
342 swaps(&stuff->height);
343 swaps(&stuff->stride);
344 return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
345}
346
347static int
348sproc_dri3_buffer_from_pixmap(ClientPtr client)
349{
350 REQUEST(xDRI3BufferFromPixmapReq);
351
352 swaps(&stuff->length);
353 swapl(&stuff->pixmap);
354 return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
355}
356
357static int
358sproc_dri3_fence_from_fd(ClientPtr client)
359{
360 REQUEST(xDRI3FenceFromFDReq);
361
362 swaps(&stuff->length);
363 swapl(&stuff->drawable);
364 swapl(&stuff->fence);
365 return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
366}
367
368static int
369sproc_dri3_fd_from_fence(ClientPtr client)
370{
371 REQUEST(xDRI3FDFromFenceReq);
372
373 swaps(&stuff->length);
374 swapl(&stuff->drawable);
375 swapl(&stuff->fence);
376 return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
377}
378
379int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
380 sproc_dri3_query_version, /* 0 */
381 sproc_dri3_open, /* 1 */
382 sproc_dri3_pixmap_from_buffer, /* 2 */
383 sproc_dri3_buffer_from_pixmap, /* 3 */
384 sproc_dri3_fence_from_fd, /* 4 */
385 sproc_dri3_fd_from_fence, /* 5 */
386};
387
388int
389sproc_dri3_dispatch(ClientPtr client)
390{
391 REQUEST(xReq);
392 if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data])
393 return BadRequest;
394 return (*sproc_dri3_vector[stuff->data]) (client);
395}