Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /************************************************************************** |
2 | ||
3 | Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. | |
4 | Copyright 2000 VA Linux Systems, Inc. | |
5 | Copyright (c) 2002, 2009-2012 Apple Inc. | |
6 | All Rights Reserved. | |
7 | ||
8 | Permission is hereby granted, free of charge, to any person obtaining a | |
9 | copy of this software and associated documentation files (the | |
10 | "Software"), to deal in the Software without restriction, including | |
11 | without limitation the rights to use, copy, modify, merge, publish, | |
12 | distribute, sub license, and/or sell copies of the Software, and to | |
13 | permit persons to whom the Software is furnished to do so, subject to | |
14 | the following conditions: | |
15 | ||
16 | The above copyright notice and this permission notice (including the | |
17 | next paragraph) shall be included in all copies or substantial portions | |
18 | of the Software. | |
19 | ||
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
21 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | |
23 | IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR | |
24 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
25 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
26 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
27 | ||
28 | **************************************************************************/ | |
29 | ||
30 | /* | |
31 | * Authors: | |
32 | * Kevin E. Martin <martin@valinux.com> | |
33 | * Jens Owen <jens@valinux.com> | |
34 | * Rickard E. (Rik) Faith <faith@valinux.com> | |
35 | * Jeremy Huddleston <jeremyhu@apple.com> | |
36 | * | |
37 | */ | |
38 | ||
39 | #ifdef HAVE_DIX_CONFIG_H | |
40 | #include <dix-config.h> | |
41 | #endif | |
42 | ||
43 | #include <X11/X.h> | |
44 | #include <X11/Xproto.h> | |
45 | #include "misc.h" | |
46 | #include "dixstruct.h" | |
47 | #include "extnsionst.h" | |
48 | #include "colormapst.h" | |
49 | #include "cursorstr.h" | |
50 | #include "scrnintstr.h" | |
51 | #include "servermd.h" | |
52 | #define _APPLEDRI_SERVER_ | |
53 | #include "appledristr.h" | |
54 | #include "swaprep.h" | |
55 | #include "dri.h" | |
56 | #include "dristruct.h" | |
57 | #include "xpr.h" | |
58 | #include "x-hash.h" | |
59 | #include "protocol-versions.h" | |
60 | ||
61 | static int DRIErrorBase = 0; | |
62 | ||
63 | static void | |
64 | AppleDRIResetProc(ExtensionEntry* extEntry); | |
65 | static int | |
66 | ProcAppleDRICreatePixmap(ClientPtr client); | |
67 | ||
68 | static unsigned char DRIReqCode = 0; | |
69 | static int DRIEventBase = 0; | |
70 | ||
71 | static void | |
72 | SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to); | |
73 | ||
74 | typedef struct _DRIEvent *DRIEventPtr; | |
75 | typedef struct _DRIEvent { | |
76 | DRIEventPtr next; | |
77 | ClientPtr client; | |
78 | XID clientResource; | |
79 | unsigned int mask; | |
80 | } DRIEventRec; | |
81 | ||
82 | /*ARGSUSED*/ | |
83 | static void | |
84 | AppleDRIResetProc(ExtensionEntry* extEntry) | |
85 | { | |
86 | DRIReset(); | |
87 | } | |
88 | ||
89 | static int | |
90 | ProcAppleDRIQueryVersion(register ClientPtr client) | |
91 | { | |
92 | xAppleDRIQueryVersionReply rep; | |
93 | ||
94 | REQUEST_SIZE_MATCH(xAppleDRIQueryVersionReq); | |
95 | rep.type = X_Reply; | |
96 | rep.length = 0; | |
97 | rep.sequenceNumber = client->sequence; | |
98 | rep.majorVersion = SERVER_APPLEDRI_MAJOR_VERSION; | |
99 | rep.minorVersion = SERVER_APPLEDRI_MINOR_VERSION; | |
100 | rep.patchVersion = SERVER_APPLEDRI_PATCH_VERSION; | |
101 | if (client->swapped) { | |
102 | swaps(&rep.sequenceNumber); | |
103 | swapl(&rep.length); | |
104 | swaps(&rep.majorVersion); | |
105 | swaps(&rep.minorVersion); | |
106 | swapl(&rep.patchVersion); | |
107 | } | |
108 | WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), &rep); | |
109 | return Success; | |
110 | } | |
111 | ||
112 | /* surfaces */ | |
113 | ||
114 | static int | |
115 | ProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client) | |
116 | { | |
117 | xAppleDRIQueryDirectRenderingCapableReply rep; | |
118 | Bool isCapable; | |
119 | ||
120 | REQUEST(xAppleDRIQueryDirectRenderingCapableReq); | |
121 | REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq); | |
122 | rep.type = X_Reply; | |
123 | rep.length = 0; | |
124 | rep.sequenceNumber = client->sequence; | |
125 | ||
126 | if (stuff->screen >= screenInfo.numScreens) { | |
127 | return BadValue; | |
128 | } | |
129 | ||
130 | if (!DRIQueryDirectRenderingCapable(screenInfo.screens[stuff->screen], | |
131 | &isCapable)) { | |
132 | return BadValue; | |
133 | } | |
134 | rep.isCapable = isCapable; | |
135 | ||
136 | if (!client->local) | |
137 | rep.isCapable = 0; | |
138 | ||
139 | if (client->swapped) { | |
140 | swaps(&rep.sequenceNumber); | |
141 | swapl(&rep.length); | |
142 | } | |
143 | ||
144 | WriteToClient(client, | |
145 | sizeof(xAppleDRIQueryDirectRenderingCapableReply), | |
146 | &rep); | |
147 | return Success; | |
148 | } | |
149 | ||
150 | static int | |
151 | ProcAppleDRIAuthConnection(register ClientPtr client) | |
152 | { | |
153 | xAppleDRIAuthConnectionReply rep; | |
154 | ||
155 | REQUEST(xAppleDRIAuthConnectionReq); | |
156 | REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq); | |
157 | ||
158 | rep.type = X_Reply; | |
159 | rep.length = 0; | |
160 | rep.sequenceNumber = client->sequence; | |
161 | rep.authenticated = 1; | |
162 | ||
163 | if (!DRIAuthConnection(screenInfo.screens[stuff->screen], | |
164 | stuff->magic)) { | |
165 | ErrorF("Failed to authenticate %u\n", (unsigned int)stuff->magic); | |
166 | rep.authenticated = 0; | |
167 | } | |
168 | ||
169 | if (client->swapped) { | |
170 | swaps(&rep.sequenceNumber); | |
171 | swapl(&rep.length); | |
172 | swapl(&rep.authenticated); /* Yes, this is a CARD32 ... sigh */ | |
173 | } | |
174 | ||
175 | WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), &rep); | |
176 | return Success; | |
177 | } | |
178 | ||
179 | static void | |
180 | surface_notify(void *_arg, | |
181 | void *data) | |
182 | { | |
183 | DRISurfaceNotifyArg *arg = _arg; | |
184 | int client_index = (int)x_cvt_vptr_to_uint(data); | |
185 | xAppleDRINotifyEvent se; | |
186 | ||
187 | if (client_index < 0 || client_index >= currentMaxClients) | |
188 | return; | |
189 | ||
190 | se.type = DRIEventBase + AppleDRISurfaceNotify; | |
191 | se.kind = arg->kind; | |
192 | se.arg = arg->id; | |
193 | se.time = currentTime.milliseconds; | |
194 | WriteEventsToClient(clients[client_index], 1, (xEvent *)&se); | |
195 | } | |
196 | ||
197 | static int | |
198 | ProcAppleDRICreateSurface(ClientPtr client) | |
199 | { | |
200 | xAppleDRICreateSurfaceReply rep; | |
201 | DrawablePtr pDrawable; | |
202 | xp_surface_id sid; | |
203 | unsigned int key[2]; | |
204 | int rc; | |
205 | ||
206 | REQUEST(xAppleDRICreateSurfaceReq); | |
207 | REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq); | |
208 | rep.type = X_Reply; | |
209 | rep.length = 0; | |
210 | rep.sequenceNumber = client->sequence; | |
211 | ||
212 | rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, | |
213 | DixReadAccess); | |
214 | if (rc != Success) | |
215 | return rc; | |
216 | ||
217 | rep.key_0 = rep.key_1 = rep.uid = 0; | |
218 | ||
219 | if (!DRICreateSurface(screenInfo.screens[stuff->screen], | |
220 | (Drawable)stuff->drawable, pDrawable, | |
221 | stuff->client_id, &sid, key, | |
222 | surface_notify, | |
223 | x_cvt_uint_to_vptr(client->index))) { | |
224 | return BadValue; | |
225 | } | |
226 | ||
227 | rep.key_0 = key[0]; | |
228 | rep.key_1 = key[1]; | |
229 | rep.uid = sid; | |
230 | ||
231 | if (client->swapped) { | |
232 | swaps(&rep.sequenceNumber); | |
233 | swapl(&rep.length); | |
234 | swapl(&rep.key_0); | |
235 | swapl(&rep.key_1); | |
236 | swapl(&rep.uid); | |
237 | } | |
238 | ||
239 | WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), &rep); | |
240 | return Success; | |
241 | } | |
242 | ||
243 | static int | |
244 | ProcAppleDRIDestroySurface(register ClientPtr client) | |
245 | { | |
246 | int rc; | |
247 | REQUEST(xAppleDRIDestroySurfaceReq); | |
248 | DrawablePtr pDrawable; | |
249 | REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq); | |
250 | ||
251 | rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, | |
252 | DixReadAccess); | |
253 | if (rc != Success) | |
254 | return rc; | |
255 | ||
256 | if (!DRIDestroySurface(screenInfo.screens[stuff->screen], | |
257 | (Drawable)stuff->drawable, | |
258 | pDrawable, NULL, NULL)) { | |
259 | return BadValue; | |
260 | } | |
261 | ||
262 | return Success; | |
263 | } | |
264 | ||
265 | static int | |
266 | ProcAppleDRICreatePixmap(ClientPtr client) | |
267 | { | |
268 | REQUEST(xAppleDRICreatePixmapReq); | |
269 | DrawablePtr pDrawable; | |
270 | int rc; | |
271 | char path[PATH_MAX]; | |
272 | xAppleDRICreatePixmapReply rep; | |
273 | int width, height, pitch, bpp; | |
274 | void *ptr; | |
275 | ||
276 | REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq); | |
277 | ||
278 | rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, | |
279 | DixReadAccess); | |
280 | ||
281 | if (rc != Success) | |
282 | return rc; | |
283 | ||
284 | if (!DRICreatePixmap(screenInfo.screens[stuff->screen], | |
285 | (Drawable)stuff->drawable, | |
286 | pDrawable, | |
287 | path, PATH_MAX)) { | |
288 | return BadValue; | |
289 | } | |
290 | ||
291 | if (!DRIGetPixmapData(pDrawable, &width, &height, | |
292 | &pitch, &bpp, &ptr)) { | |
293 | return BadValue; | |
294 | } | |
295 | ||
296 | rep.stringLength = strlen(path) + 1; | |
297 | ||
298 | rep.type = X_Reply; | |
299 | rep.length = bytes_to_int32(rep.stringLength); | |
300 | rep.sequenceNumber = client->sequence; | |
301 | rep.width = width; | |
302 | rep.height = height; | |
303 | rep.pitch = pitch; | |
304 | rep.bpp = bpp; | |
305 | rep.size = pitch * height; | |
306 | ||
307 | if (sizeof(rep) != sz_xAppleDRICreatePixmapReply) | |
308 | ErrorF("error sizeof(rep) is %zu\n", sizeof(rep)); | |
309 | ||
310 | if (client->swapped) { | |
311 | swaps(&rep.sequenceNumber); | |
312 | swapl(&rep.length); | |
313 | swapl(&rep.stringLength); | |
314 | swapl(&rep.width); | |
315 | swapl(&rep.height); | |
316 | swapl(&rep.pitch); | |
317 | swapl(&rep.bpp); | |
318 | swapl(&rep.size); | |
319 | } | |
320 | ||
321 | WriteToClient(client, sizeof(rep), &rep); | |
322 | WriteToClient(client, rep.stringLength, path); | |
323 | ||
324 | return Success; | |
325 | } | |
326 | ||
327 | static int | |
328 | ProcAppleDRIDestroyPixmap(ClientPtr client) | |
329 | { | |
330 | DrawablePtr pDrawable; | |
331 | int rc; | |
332 | REQUEST(xAppleDRIDestroyPixmapReq); | |
333 | REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq); | |
334 | ||
335 | rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, | |
336 | DixReadAccess); | |
337 | ||
338 | if (rc != Success) | |
339 | return rc; | |
340 | ||
341 | DRIDestroyPixmap(pDrawable); | |
342 | ||
343 | return Success; | |
344 | } | |
345 | ||
346 | /* dispatch */ | |
347 | ||
348 | static int | |
349 | ProcAppleDRIDispatch(register ClientPtr client) | |
350 | { | |
351 | REQUEST(xReq); | |
352 | ||
353 | switch (stuff->data) { | |
354 | case X_AppleDRIQueryVersion: | |
355 | return ProcAppleDRIQueryVersion(client); | |
356 | ||
357 | case X_AppleDRIQueryDirectRenderingCapable: | |
358 | return ProcAppleDRIQueryDirectRenderingCapable(client); | |
359 | } | |
360 | ||
361 | if (!client->local) | |
362 | return DRIErrorBase + AppleDRIClientNotLocal; | |
363 | ||
364 | switch (stuff->data) { | |
365 | case X_AppleDRIAuthConnection: | |
366 | return ProcAppleDRIAuthConnection(client); | |
367 | ||
368 | case X_AppleDRICreateSurface: | |
369 | return ProcAppleDRICreateSurface(client); | |
370 | ||
371 | case X_AppleDRIDestroySurface: | |
372 | return ProcAppleDRIDestroySurface(client); | |
373 | ||
374 | case X_AppleDRICreatePixmap: | |
375 | return ProcAppleDRICreatePixmap(client); | |
376 | ||
377 | case X_AppleDRIDestroyPixmap: | |
378 | return ProcAppleDRIDestroyPixmap(client); | |
379 | ||
380 | default: | |
381 | return BadRequest; | |
382 | } | |
383 | } | |
384 | ||
385 | static void | |
386 | SNotifyEvent(xAppleDRINotifyEvent *from, | |
387 | xAppleDRINotifyEvent *to) | |
388 | { | |
389 | to->type = from->type; | |
390 | to->kind = from->kind; | |
391 | cpswaps(from->sequenceNumber, to->sequenceNumber); | |
392 | cpswapl(from->time, to->time); | |
393 | cpswapl(from->arg, to->arg); | |
394 | } | |
395 | ||
396 | static int | |
397 | SProcAppleDRIQueryVersion(register ClientPtr client) | |
398 | { | |
399 | REQUEST(xAppleDRIQueryVersionReq); | |
400 | swaps(&stuff->length); | |
401 | return ProcAppleDRIQueryVersion(client); | |
402 | } | |
403 | ||
404 | static int | |
405 | SProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client) | |
406 | { | |
407 | REQUEST(xAppleDRIQueryDirectRenderingCapableReq); | |
408 | swaps(&stuff->length); | |
409 | REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq); | |
410 | swapl(&stuff->screen); | |
411 | return ProcAppleDRIQueryDirectRenderingCapable(client); | |
412 | } | |
413 | ||
414 | static int | |
415 | SProcAppleDRIAuthConnection(register ClientPtr client) | |
416 | { | |
417 | REQUEST(xAppleDRIAuthConnectionReq); | |
418 | swaps(&stuff->length); | |
419 | REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq); | |
420 | swapl(&stuff->screen); | |
421 | swapl(&stuff->magic); | |
422 | return ProcAppleDRIAuthConnection(client); | |
423 | } | |
424 | ||
425 | static int | |
426 | SProcAppleDRICreateSurface(register ClientPtr client) | |
427 | { | |
428 | REQUEST(xAppleDRICreateSurfaceReq); | |
429 | swaps(&stuff->length); | |
430 | REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq); | |
431 | swapl(&stuff->screen); | |
432 | swapl(&stuff->drawable); | |
433 | swapl(&stuff->client_id); | |
434 | return ProcAppleDRICreateSurface(client); | |
435 | } | |
436 | ||
437 | static int | |
438 | SProcAppleDRIDestroySurface(register ClientPtr client) | |
439 | { | |
440 | REQUEST(xAppleDRIDestroySurfaceReq); | |
441 | swaps(&stuff->length); | |
442 | REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq); | |
443 | swapl(&stuff->screen); | |
444 | swapl(&stuff->drawable); | |
445 | return ProcAppleDRIDestroySurface(client); | |
446 | } | |
447 | ||
448 | static int | |
449 | SProcAppleDRICreatePixmap(register ClientPtr client) | |
450 | { | |
451 | REQUEST(xAppleDRICreatePixmapReq); | |
452 | swaps(&stuff->length); | |
453 | REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq); | |
454 | swapl(&stuff->screen); | |
455 | swapl(&stuff->drawable); | |
456 | return ProcAppleDRICreatePixmap(client); | |
457 | } | |
458 | ||
459 | static int | |
460 | SProcAppleDRIDestroyPixmap(register ClientPtr client) | |
461 | { | |
462 | REQUEST(xAppleDRIDestroyPixmapReq); | |
463 | swaps(&stuff->length); | |
464 | REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq); | |
465 | swapl(&stuff->drawable); | |
466 | return ProcAppleDRIDestroyPixmap(client); | |
467 | } | |
468 | ||
469 | static int | |
470 | SProcAppleDRIDispatch(register ClientPtr client) | |
471 | { | |
472 | REQUEST(xReq); | |
473 | ||
474 | switch (stuff->data) { | |
475 | case X_AppleDRIQueryVersion: | |
476 | return SProcAppleDRIQueryVersion(client); | |
477 | ||
478 | case X_AppleDRIQueryDirectRenderingCapable: | |
479 | return SProcAppleDRIQueryDirectRenderingCapable(client); | |
480 | } | |
481 | ||
482 | if (!client->local) | |
483 | return DRIErrorBase + AppleDRIClientNotLocal; | |
484 | ||
485 | switch (stuff->data) { | |
486 | case X_AppleDRIAuthConnection: | |
487 | return SProcAppleDRIAuthConnection(client); | |
488 | ||
489 | case X_AppleDRICreateSurface: | |
490 | return SProcAppleDRICreateSurface(client); | |
491 | ||
492 | case X_AppleDRIDestroySurface: | |
493 | return SProcAppleDRIDestroySurface(client); | |
494 | ||
495 | case X_AppleDRICreatePixmap: | |
496 | return SProcAppleDRICreatePixmap(client); | |
497 | ||
498 | case X_AppleDRIDestroyPixmap: | |
499 | return SProcAppleDRIDestroyPixmap(client); | |
500 | ||
501 | default: | |
502 | return BadRequest; | |
503 | } | |
504 | } | |
505 | ||
506 | void | |
507 | AppleDRIExtensionInit(void) | |
508 | { | |
509 | ExtensionEntry* extEntry; | |
510 | ||
511 | if (DRIExtensionInit() && | |
512 | (extEntry = AddExtension(APPLEDRINAME, | |
513 | AppleDRINumberEvents, | |
514 | AppleDRINumberErrors, | |
515 | ProcAppleDRIDispatch, | |
516 | SProcAppleDRIDispatch, | |
517 | AppleDRIResetProc, | |
518 | StandardMinorOpcode))) { | |
519 | size_t i; | |
520 | DRIReqCode = (unsigned char)extEntry->base; | |
521 | DRIErrorBase = extEntry->errorBase; | |
522 | DRIEventBase = extEntry->eventBase; | |
523 | for (i = 0; i < AppleDRINumberEvents; i++) | |
524 | EventSwapVector[DRIEventBase + i] = (EventSwapPtr)SNotifyEvent; | |
525 | } | |
526 | } |